package lian

import (
	"context"
	"github.com/muktihari/fit/profile/mesgdef"
	"github.com/muktihari/fit/profile/typedef"
	"github.com/muktihari/fit/proto"
	"github.com/twpayne/go-geom"
	"github.com/uptrace/bun"
	"time"
)

// ========= 用户与基础信息 =========

// User 结构体代表 users 表 (对应 FHIR Patient 或 Practitioner)
type User struct {
	bun.BaseModel `bun:"table:users,alias:u"`

	UserID             int64     `bun:"user_id,pk,autoincrement"`
	Username           string    `bun:"username,unique,notnull"`
	Email              *string   `bun:"email,unique,nullzero"`
	UserType           string    `bun:"user_type,notnull,default:'PATIENT'"` // 'PATIENT', 'PRACTITIONER'
	FhirPatientID      *string   `bun:"fhir_patient_id,unique,nullzero"`
	FhirPractitionerID *string   `bun:"fhir_practitioner_id,unique,nullzero"`
	CreatedAt          time.Time `bun:"created_at,notnull,default:current_timestamp"`
	UpdatedAt          time.Time `bun:"updated_at,notnull,default:current_timestamp"`

	// 关系 (Relationships)
	// 作为患者的关系
	PatientDietLogs        []*DietLog         `bun:"rel:has-many,join:user_id=user_id"`           // 患者的饮食日志
	PatientMeasurements    []*UserMeasurement `bun:"rel:has-many,join:user_id=user_id"`           // 患者的测量记录
	PatientGoals           []*UserGoal        `bun:"rel:has-many,join:user_id=user_id"`           // 患者的目标
	PatientServiceRequests []*ServiceRequest  `bun:"rel:has-many,join:requester_user_id=user_id"` // 患者发出的服务请求
	PatientNutritionOrders []*NutritionOrder  `bun:"rel:has-many,join:patient_user_id=user_id"`   // 患者的营养医嘱

	// 作为医生/营养师的关系
	PractitionerServiceRequests []*ServiceRequest `bun:"rel:has-many,join:performer_user_id=user_id"` // 医生处理的服务请求
	PractitionerNutritionOrders []*NutritionOrder `bun:"rel:has-many,join:orderer_user_id=user_id"`   // 医生开具的营养医嘱

	// 作为创建者的关系
	UserRecipes []*BaseFoodProduct `bun:"rel:has-many,join:user_id=user_id"` // 用户创建的食谱
}

// Unit 结构体代表 units 表 (映射 UCUM)
type Unit struct {
	bun.BaseModel `bun:"table:units,alias:un"`

	UnitID       int32   `bun:"unit_id,pk,autoincrement"`
	Name         string  `bun:"name,unique,notnull"`
	Abbreviation *string `bun:"abbreviation,unique,nullzero"`
	UcumCode     string  `bun:"ucum_code,unique,notnull"`
	Description  *string `bun:"description,nullzero"`
}

// Nutrient 结构体代表 nutrients 表 (对应 FHIR Nutrient Concepts)
type Nutrient struct {
	bun.BaseModel `bun:"table:nutrients,alias:n"`

	NutrientID    int32   `bun:"nutrient_id,pk,autoincrement"`
	Name          string  `bun:"name,unique,notnull"`
	DefaultUnitID int32   `bun:"default_unit_id,notnull"`
	FhirLoincCode *string `bun:"fhir_loinc_code,unique,nullzero"`
	DecimalPlaces int16   `bun:"decimal_places,notnull,default:1"`
	Description   *string `bun:"description,nullzero"`

	// 关系 (Relationships)
	DefaultUnit *Unit `bun:"rel:belongs-to,join:default_unit_id=unit_id"`
}

// MealType 结构体代表 meal_types 表
type MealType struct {
	bun.BaseModel `bun:"table:meal_types,alias:mt"`

	MealTypeID     int32   `bun:"meal_type_id,pk,autoincrement"`
	Name           string  `bun:"name,unique,notnull"`
	FhirCodeSystem *string `bun:"fhir_code_system,nullzero"`
	FhirCode       *string `bun:"fhir_code,unique,nullzero"`
}

// MeasurementType 结构体代表 measurement_types 表
type MeasurementType struct {
	bun.BaseModel `bun:"table:measurement_types,alias:met"`

	MeasurementTypeID int32  `bun:"measurement_type_id,pk,autoincrement"`
	Name              string `bun:"name,unique,notnull"`
	FhirLoincCode     string `bun:"fhir_loinc_code,unique,notnull"`
	DefaultUnitID     int32  `bun:"default_unit_id,notnull"`

	// 关系 (Relationships)
	DefaultUnit *Unit `bun:"rel:belongs-to,join:default_unit_id=unit_id"`
}

// ========= 食物产品定义 (对应 FHIR NutritionProduct) =========

// BaseFoodProduct 结构体代表 base_food_products 表
type BaseFoodProduct struct {
	bun.BaseModel `bun:"table:base_food_products,alias:bfp"`

	BaseProductID          int64     `bun:"base_product_id,pk,autoincrement"`
	Name                   string    `bun:"name,notnull"`
	BrandName              *string   `bun:"brand_name,nullzero"`
	Description            *string   `bun:"description,nullzero"`
	FoodType               string    `bun:"food_type,notnull"` // 'BASE_INGREDIENT', 'PREDEFINED_RECIPE', 'USER_RECIPE'
	UserID                 *int64    `bun:"user_id,nullzero"`
	FhirCodeSystem         *string   `bun:"fhir_code_system,nullzero"`
	FhirCode               *string   `bun:"fhir_code,nullzero"`
	FhirNutritionProductID *string   `bun:"fhir_nutrition_product_id,unique,nullzero"`
	IsConfigurable         bool      `bun:"is_configurable,notnull,default:false"`
	CreatedAt              time.Time `bun:"created_at,notnull,default:current_timestamp"`
	UpdatedAt              time.Time `bun:"updated_at,notnull,default:current_timestamp"`

	// 关系 (Relationships)
	User              *User                     `bun:"rel:belongs-to,join:user_id=user_id"`
	Nutrients         []*BaseProductNutrient    `bun:"rel:has-many,join:base_product_id=base_product_id"`
	AvailableOptions  []*FoodOption             `bun:"m2m:base_product_available_options,join:BaseFoodProduct=FoodOption"`
	OptionGroupRules  []*ProductOptionGroupRule `bun:"rel:has-many,join:base_product_id=base_product_id"`
	RecipeIngredients []*RecipeIngredient       `bun:"rel:has-many,join:base_product_id=recipe_product_id"`
	//IngredientInRecipes []*RecipeIngredient                 `bun:"rel:has-many,join:base_product_id=ingredient_product_id"`
	OptionImpacts       []*FoodOptionNutrientImpact         `bun:"rel:has-many,join:base_product_id=applies_to_base_product_id"`
	FoodRecommendations []*NutritionOrderFoodRecommendation `bun:"rel:has-many,join:base_product_id=base_product_id"` // **新增**: 食物作为建议/限制出现在哪些医嘱中
}

type FoodCategory struct {
	bun.BaseModel `bun:"table:food_categories,alias:fc"`

	ID               int64   `bun:"id,pk,autoincrement"`
	Name             string  `bun:"name,notnull"`
	ParentCategoryID *int64  `bun:"parent_category_id,nullzero"` // 使用指针表示可空
	Description      *string `bun:"description,nullzero"`
	// UserID        *int64 `bun:"user_id,nullzero"` // 如果允许用户自定义分类
	CreatedAt time.Time `bun:"created_at,notnull,default:current_timestamp"`
	UpdatedAt time.Time `bun:"updated_at,notnull,default:current_timestamp"`

	// 关系 (Relationships)
	ParentCategory   *FoodCategory      `bun:"rel:belongs-to,join:parent_category_id=id"`
	Children         []*FoodCategory    `bun:"rel:has-many,join:id=parent_category_id"`                       // 子分类
	BaseFoodProducts []*BaseFoodProduct `bun:"m2m:food_category_relations,join:FoodCategory=BaseFoodProduct"` // 此分类下的所有食物
}

// FoodCategoryRelation 结构体代表 food_category_relations 连接表
// (BaseFoodProduct 与 FoodCategory 的多对多关系)
type FoodCategoryRelation struct {
	bun.BaseModel `bun:"table:food_category_relations,alias:fcr"`

	FoodCategoryID    int64            `bun:"food_category_id,pk"`
	FoodCategory      *FoodCategory    `bun:"rel:belongs-to,join:food_category_id=id"`
	BaseFoodProductID int64            `bun:"base_product_id,pk"` // 列名与数据库一致
	BaseFoodProduct   *BaseFoodProduct `bun:"rel:belongs-to,join:base_product_id=base_product_id"`
}

type UserMenu struct {
	bun.BaseModel `bun:"table:user_menus,alias:um"`

	ID          int64     `bun:"id,pk,autoincrement"`
	UserID      int64     `bun:"user_id,notnull"` // 关联创建菜单的用户
	Name        string    `bun:"name,notnull"`
	Description *string   `bun:"description,nullzero"`
	SortOrder   int       `bun:"sort_order,default:0"`
	CreatedAt   time.Time `bun:"created_at,notnull,default:current_timestamp"`
	UpdatedAt   time.Time `bun:"updated_at,notnull,default:current_timestamp"`

	// 关系 (Relationships)
	User  *User              `bun:"rel:belongs-to,join:user_id=user_id"`
	Items []*BaseFoodProduct `bun:"m2m:menu_food_items,join:UserMenu=BaseFoodProduct"` // 菜单中包含的食物项

	// UI 辅助字段，不在数据库中，应用层填充
	FoodCategoriesInMenu []*FoodCategory `bun:"-"` // 用于在UI上展示此菜单下食物涉及的所有分类
}

// MenuFoodItem 结构体代表 menu_food_items 连接表
// (UserMenu 与 BaseFoodProduct 的多对多关系，表示菜单中的食物项)
type MenuFoodItem struct {
	bun.BaseModel `bun:"table:menu_food_items,alias:mfi"`

	MenuID            int64            `bun:"menu_id,pk"`
	UserMenu          *UserMenu        `bun:"rel:belongs-to,join:menu_id=id"`
	BaseFoodProductID int64            `bun:"base_product_id,pk"` // 列名与数据库一致
	BaseFoodProduct   *BaseFoodProduct `bun:"rel:belongs-to,join:base_product_id=base_product_id"`
	SortOrder         int              `bun:"sort_order,default:0"` // 食物在菜单中的排序
	AddedAt           time.Time        `bun:"added_at,notnull,default:current_timestamp"`
}

// BaseProductNutrient 结构体代表 base_product_nutrients 表
type BaseProductNutrient struct {
	bun.BaseModel `bun:"table:base_product_nutrients,alias:bpn"`

	BaseProductNutrientID int64    `bun:"base_product_nutrient_id,pk,autoincrement"`
	BaseProductID         int64    `bun:"base_product_id,notnull"`
	NutrientID            int32    `bun:"nutrient_id,notnull"`
	AmountPer100Unit      *float64 `bun:"amount_per_100_unit,type:numeric(18,9),nullzero"`
	AmountPer100UnitID    *int32   `bun:"amount_per_100_unit_id,nullzero"`
	AmountPerServing      *float64 `bun:"amount_per_serving,type:numeric(18,9),nullzero"`
	ServingSizeValue      *float64 `bun:"serving_size_value,type:numeric(10,2),nullzero"`
	ServingSizeUnitID     *int32   `bun:"serving_size_unit_id,nullzero"`

	// 关系 (Relationships)
	BaseFoodProduct *BaseFoodProduct `bun:"rel:belongs-to,join:base_product_id=base_product_id"`
	Nutrient        *Nutrient        `bun:"rel:belongs-to,join:nutrient_id=nutrient_id"`
	AmountUnit      *Unit            `bun:"rel:belongs-to,join:amount_per_100_unit_id=unit_id"`
	ServingUnit     *Unit            `bun:"rel:belongs-to,join:serving_size_unit_id=unit_id"`
}

// RecipeIngredient 结构体代表 recipe_ingredients 表
type RecipeIngredient struct {
	bun.BaseModel `bun:"table:recipe_ingredients,alias:ri"`

	RecipeIngredientID  int64    `bun:"recipe_ingredient_id,pk,autoincrement"`
	RecipeProductID     int64    `bun:"recipe_product_id,notnull"`
	IngredientProductID int64    `bun:"ingredient_product_id,notnull"`
	Quantity            *float64 `bun:"quantity,type:numeric(10,3),nullzero"`
	UnitID              *int32   `bun:"unit_id,nullzero"`
	IngredientOrder     *int16   `bun:"ingredient_order,nullzero"`
	Notes               *string  `bun:"notes,nullzero"`

	// 关系 (Relationships)
	RecipeProduct     *BaseFoodProduct `bun:"rel:belongs-to,join:recipe_product_id=base_product_id"`
	IngredientProduct *BaseFoodProduct `bun:"rel:belongs-to,join:ingredient_product_id=base_product_id"`
	Unit              *Unit            `bun:"rel:belongs-to,join:unit_id=unit_id"`
}

// FoodOption 结构体代表 food_options 表
type FoodOption struct {
	bun.BaseModel `bun:"table:food_options,alias:fo"`

	OptionID        int64   `bun:"option_id,pk,autoincrement"`
	OptionGroupName string  `bun:"option_group_name,notnull"`
	OptionName      string  `bun:"option_name,notnull"`
	Description     *string `bun:"description,nullzero"`
	FhirCodeSystem  *string `bun:"fhir_code_system,nullzero"`
	FhirCode        *string `bun:"fhir_code,nullzero"`

	// 关系 (Relationships)
	//AvailableForProducts []*BaseFoodProduct `bun:"m2m:base_product_available_options,join:FoodOption=BaseFoodProduct"`
	NutrientImpacts []*FoodOptionNutrientImpact `bun:"rel:has-many,join:option_id=option_id"`
	//SelectedInItems []*DietLogItem `bun:"m2m:diet_log_item_selected_options,join:FoodOption=DietLogItem"` // **新增**: 选项被哪些日志条目选中
}

// BaseProductAvailableOption 结构体代表 base_product_available_options 连接表
type BaseProductAvailableOption struct {
	bun.BaseModel `bun:"table:base_product_available_options,alias:bpao"`

	BaseProductID int64 `bun:"base_product_id,pk"`
	OptionID      int64 `bun:"option_id,pk"`
	IsDefault     bool  `bun:"is_default,notnull,default:false"`
	DisplayOrder  int16 `bun:"display_order,default:0"`

	// 关系 (Relationships)
	BaseFoodProduct *BaseFoodProduct `bun:"rel:belongs-to,join:base_product_id=base_product_id"`
	FoodOption      *FoodOption      `bun:"rel:belongs-to,join:option_id=option_id"`
}

// ProductOptionGroupRule 结构体代表 product_option_group_rules 表
type ProductOptionGroupRule struct {
	bun.BaseModel `bun:"table:product_option_group_rules,alias:pogr"`

	RuleID          int32  `bun:"rule_id,pk,autoincrement"`
	BaseProductID   int64  `bun:"base_product_id,notnull"`
	OptionGroupName string `bun:"option_group_name,notnull"`
	MinSelected     int16  `bun:"min_selected,notnull,default:0"`
	MaxSelected     int16  `bun:"max_selected,notnull,default:1"`

	// 关系 (Relationships)
	BaseFoodProduct *BaseFoodProduct `bun:"rel:belongs-to,join:base_product_id=base_product_id"`
}

// FoodOptionNutrientImpact 结构体代表 food_option_nutrient_impacts 表
type FoodOptionNutrientImpact struct {
	bun.BaseModel `bun:"table:food_option_nutrient_impacts,alias:foni"`

	OptionImpactID         int64    `bun:"option_impact_id,pk,autoincrement"`
	OptionID               int64    `bun:"option_id,notnull"`
	AppliesToBaseProductID *int64   `bun:"applies_to_base_product_id,nullzero"`
	NutrientID             int32    `bun:"nutrient_id,notnull"`
	ChangeAmount           *float64 `bun:"change_amount,type:numeric(18,9),nullzero"`
	AbsoluteAmount         *float64 `bun:"absolute_amount,type:numeric(18,9),nullzero"`
	UnitID                 int32    `bun:"unit_id,notnull"`
	ContextNotes           *string  `bun:"context_notes,nullzero"`

	// 关系 (Relationships)
	FoodOption      *FoodOption      `bun:"rel:belongs-to,join:option_id=option_id"`
	BaseFoodProduct *BaseFoodProduct `bun:"rel:belongs-to,join:applies_to_base_product_id=base_product_id"`
	Nutrient        *Nutrient        `bun:"rel:belongs-to,join:nutrient_id=nutrient_id"`
	Unit            *Unit            `bun:"rel:belongs-to,join:unit_id=unit_id"`
}

// ========= 用户健康数据与目标 =========

// UserMeasurement 结构体代表 user_measurements 表 (对应 FHIR Observation)
type UserMeasurement struct {
	bun.BaseModel `bun:"table:user_measurements,alias:um"`

	MeasurementID            int64     `bun:"measurement_id,pk"`
	UserID                   int64     `bun:"user_id,notnull"`
	MeasurementTypeID        int32     `bun:"measurement_type_id,notnull"`
	MeasurementTimestamp     time.Time `bun:"measurement_timestamp,pk,notnull"`
	Value                    float64   `bun:"value,type:numeric(10,3),notnull"`
	UnitID                   int32     `bun:"unit_id,notnull"`
	Notes                    *string   `bun:"notes,nullzero"`
	PartOfCarePlanActivityID *int64    `bun:"part_of_care_plan_activity_id,nullzero"` // **新增**
	CreatedAt                time.Time `bun:"created_at,notnull,default:current_timestamp"`
	FhirObservationID        *string   `bun:"fhir_observation_id,unique,nullzero"`

	// 关系 (Relationships)
	User            *User             `bun:"rel:belongs-to,join:user_id=user_id"`
	MeasurementType *MeasurementType  `bun:"rel:belongs-to,join:measurement_type_id=measurement_type_id"`
	Unit            *Unit             `bun:"rel:belongs-to,join:unit_id=unit_id"`
	PartOfActivity  *CarePlanActivity `bun:"rel:belongs-to,join:part_of_care_plan_activity_id=activity_id"` // **新增**
}

// UserGoal 结构体代表 user_goals 表 (对应 FHIR Goal)
type UserGoal struct {
	bun.BaseModel `bun:"table:user_goals,alias:ug"`

	GoalID                  int64      `bun:"goal_id,pk,autoincrement"`
	UserID                  int64      `bun:"user_id,notnull"`
	Description             string     `bun:"description,notnull"`
	TargetType              string     `bun:"target_type,notnull"`                   // 'WEIGHT_TARGET', 'BODY_FAT_TARGET', 'NUTRIENT_INTAKE', 'ACTIVITY_SPEED_TARGET', etc.
	GoalSource              string     `bun:"goal_source,notnull,default:'APP_SET'"` // 'APP_SET', 'PRACTITIONER_SET', 'DEVICE_SYNC'
	ActivityType            *string    `bun:"activity_type,nullzero"`                // 例如 'RUNNING', 'CYCLING'
	TargetMeasurementTypeID *int32     `bun:"target_measurement_type_id,nullzero"`
	TargetValue             *float64   `bun:"target_value,type:numeric(10,3),nullzero"`
	TargetUnitID            *int32     `bun:"target_unit_id,nullzero"`
	TargetNutrientID        *int32     `bun:"target_nutrient_id,nullzero"`
	TargetDate              *time.Time `bun:"target_date,type:date,nullzero"`
	Status                  string     `bun:"status,notnull,default:'active'"`
	ExternalGoalID          *string    `bun:"external_goal_id,nullzero"` // 来自外部来源的 ID
	CreatedAt               time.Time  `bun:"created_at,notnull,default:current_timestamp"`
	UpdatedAt               time.Time  `bun:"updated_at,notnull,default:current_timestamp"`
	FhirGoalID              *string    `bun:"fhir_goal_id,unique,nullzero"`

	// 关系 (Relationships)
	User                  *User            `bun:"rel:belongs-to,join:user_id=user_id"`
	TargetMeasurementType *MeasurementType `bun:"rel:belongs-to,join:target_measurement_type_id=measurement_type_id"`
	TargetUnit            *Unit            `bun:"rel:belongs-to,join:target_unit_id=unit_id"`
	TargetNutrient        *Nutrient        `bun:"rel:belongs-to,join:target_nutrient_id=nutrient_id"`
}

// ========= 医嘱与服务请求 =========

// ServiceRequest 结构体代表 service_requests 表 (对应 FHIR ServiceRequest)
type ServiceRequest struct {
	bun.BaseModel `bun:"table:service_requests,alias:sr"`

	RequestID                int64     `bun:"request_id,pk,autoincrement"`
	RequesterUserID          int64     `bun:"requester_user_id,notnull"`
	PerformerUserID          int64     `bun:"performer_user_id,notnull"`
	RequestCode              string    `bun:"request_code,notnull"`
	RequestDescription       *string   `bun:"request_description,nullzero"`
	Status                   string    `bun:"status,notnull,default:'active'"`
	Intent                   string    `bun:"intent,notnull,default:'order'"`
	Priority                 *string   `bun:"priority,nullzero"`
	ReasonText               *string   `bun:"reason_text,nullzero"`
	ReasonGoalID             *int64    `bun:"reason_goal_id,nullzero"`
	ReasonMeasurementID      *int64    `bun:"reason_measurement_id,nullzero"`
	PartOfCarePlanActivityID *int64    `bun:"part_of_care_plan_activity_id,nullzero"` // **新增**
	RequestedAt              time.Time `bun:"requested_at,notnull,default:current_timestamp"`
	FhirServicerequestID     *string   `bun:"fhir_servicerequest_id,unique,nullzero"`

	// 关系 (Relationships)
	RequesterUser     *User             `bun:"rel:belongs-to,join:requester_user_id=user_id"`
	PerformerUser     *User             `bun:"rel:belongs-to,join:performer_user_id=user_id"`
	ReasonGoal        *UserGoal         `bun:"rel:belongs-to,join:reason_goal_id=goal_id"`
	ReasonMeasurement *UserMeasurement  `bun:"rel:belongs-to,join:reason_measurement_id=measurement_id"`
	PartOfActivity    *CarePlanActivity `bun:"rel:belongs-to,join:part_of_care_plan_activity_id=activity_id"` // **新增**
}

// NutritionOrder 结构体代表 nutrition_orders 表 (对应 FHIR NutritionOrder)
type NutritionOrder struct {
	bun.BaseModel `bun:"table:nutrition_orders,alias:no"`

	OrderID                  int64     `bun:"order_id,pk,autoincrement"`
	PatientUserID            int64     `bun:"patient_user_id,notnull"` // 对于模板，此字段可能无意义或指向一个虚拟/模板患者用户
	OrdererUserID            int64     `bun:"orderer_user_id,notnull"` // 对于模板，此字段可能指向系统或模板创建者
	OrderTimestamp           time.Time `bun:"order_timestamp,notnull"`
	Status                   string    `bun:"status,notnull,default:'active'"`
	Intent                   string    `bun:"intent,notnull,default:'order'"`
	IsTemplate               bool      `bun:"is_template,notnull,default:false"`
	PartOfCarePlanActivityID *int64    `bun:"part_of_care_plan_activity_id,nullzero"`
	FhirNutritionorderID     *string   `bun:"fhir_nutritionorder_id,unique,nullzero"`

	// 关系 (Relationships)
	PatientUser     *User                     `bun:"rel:belongs-to,join:patient_user_id=user_id"`
	OrdererUser     *User                     `bun:"rel:belongs-to,join:orderer_user_id=user_id"`
	OralDiets       []*NutritionOrderOralDiet `bun:"rel:has-many,join:order_id=order_id"`
	BasedOnDietLogs []*DietLog                `bun:"rel:has-many,join:order_id=based_on_nutrition_order_id"`
	PartOfActivity  *CarePlanActivity         `bun:"rel:belongs-to,join:part_of_care_plan_activity_id=activity_id"`
}

// 注意:
// 1. 其他未修改的 struct (如 User, NutritionOrderOralDiet 等) 在此省略以保持简洁。
// 2. 当 IsTemplate 为 true 时，PatientUserID 和 OrdererUserID 的业务含义需要特别考虑。
//    - PatientUserID: 对于模板，可以考虑不设置，或者指向一个代表“所有患者”或“模板适用人群”的虚拟用户ID。
//    - OrdererUserID: 对于模板，可以指向创建该模板的系统管理员或特定营养师角色。
//    - 在实例化模板为具体患者的 NutritionOrder 时，PatientUserID 和 OrdererUserID 才会被赋予实际的患者和开具医嘱的医生ID。

// NutritionOrderOralDiet 结构体代表 nutrition_order_oral_diets 表
type NutritionOrderOralDiet struct {
	bun.BaseModel `bun:"table:nutrition_order_oral_diets,alias:nood"`

	OralDietID                 int64   `bun:"oral_diet_id,pk,autoincrement"`
	OrderID                    int64   `bun:"order_id,notnull"`
	DietTypeCodeSystem         *string `bun:"diet_type_code_system,nullzero"`
	DietTypeCode               *string `bun:"diet_type_code,nullzero"`
	DietTypeText               string  `bun:"diet_type_text,notnull"`
	TextureCodeSystem          *string `bun:"texture_code_system,nullzero"`
	TextureCode                *string `bun:"texture_code,nullzero"`
	TextureText                *string `bun:"texture_text,nullzero"`
	FluidConsistencyCodeSystem *string `bun:"fluid_consistency_code_system,nullzero"`
	FluidConsistencyCode       *string `bun:"fluid_consistency_code,nullzero"`
	FluidConsistencyText       *string `bun:"fluid_consistency_text,nullzero"`
	Instruction                *string `bun:"instruction,nullzero"`

	// 关系 (Relationships)
	NutritionOrder      *NutritionOrder                     `bun:"rel:belongs-to,join:order_id=order_id"`
	NutrientTargets     []*NutritionOrderNutrientTarget     `bun:"rel:has-many,join:oral_diet_id=oral_diet_id"` // 一个口服饮食部分有多个营养素目标
	FoodRecommendations []*NutritionOrderFoodRecommendation `bun:"rel:has-many,join:oral_diet_id=oral_diet_id"` // **新增**: 一个口服饮食部分有多个食物建议/限制
}

// NutritionOrderNutrientTarget 结构体代表 nutrition_order_nutrient_targets 表
type NutritionOrderNutrientTarget struct {
	bun.BaseModel `bun:"table:nutrition_order_nutrient_targets,alias:nont"`

	TargetID     int64   `bun:"target_id,pk,autoincrement"`
	OralDietID   int64   `bun:"oral_diet_id,notnull"`
	NutrientID   int32   `bun:"nutrient_id,notnull"`
	TargetAmount float64 `bun:"target_amount,type:numeric(18,9),notnull"`
	UnitID       int32   `bun:"unit_id,notnull"`

	// 关系 (Relationships)
	OralDiet *NutritionOrderOralDiet `bun:"rel:belongs-to,join:oral_diet_id=oral_diet_id"`
	Nutrient *Nutrient               `bun:"rel:belongs-to,join:nutrient_id=nutrient_id"`
	Unit     *Unit                   `bun:"rel:belongs-to,join:unit_id=unit_id"`
}

// **[新增]** NutritionOrderFoodRecommendation 结构体代表 nutrition_order_food_recommendations 表
type NutritionOrderFoodRecommendation struct {
	bun.BaseModel `bun:"table:nutrition_order_food_recommendations,alias:nofr"`

	RecommendationID   int64    `bun:"recommendation_id,pk,autoincrement"`
	OralDietID         int64    `bun:"oral_diet_id,notnull"`
	BaseProductID      int64    `bun:"base_product_id,notnull"`
	RecommendationType string   `bun:"recommendation_type,notnull"` // 'RECOMMENDED', 'ALLOWED', 'DISCOURAGED', 'FORBIDDEN'
	SuggestedQuantity  *float64 `bun:"suggested_quantity,type:numeric(10,3),nullzero"`
	SuggestedUnitID    *int32   `bun:"suggested_unit_id,nullzero"`
	FrequencyText      *string  `bun:"frequency_text,nullzero"`
	Notes              *string  `bun:"notes,nullzero"`

	// 关系 (Relationships)
	OralDiet        *NutritionOrderOralDiet `bun:"rel:belongs-to,join:oral_diet_id=oral_diet_id"`
	BaseFoodProduct *BaseFoodProduct        `bun:"rel:belongs-to,join:base_product_id=base_product_id"`
	SuggestedUnit   *Unit                   `bun:"rel:belongs-to,join:suggested_unit_id=unit_id"`
}

// ========= 饮食日志记录 (对应 FHIR NutritionIntake 及关联 Observation) =========

// DietLog 结构体代表 diet_logs 表
type DietLog struct {
	bun.BaseModel `bun:"table:diet_logs,alias:dl"`

	LogID                   int64     `bun:"log_id,pk"` // 复合主键的一部分
	UserID                  int64     `bun:"user_id,notnull"`
	LogTimestamp            time.Time `bun:"log_timestamp,pk,notnull"` // 复合主键的一部分，也是分区键
	TimezoneOffset          *string   `bun:"timezone_offset,nullzero"`
	MealTypeID              int32     `bun:"meal_type_id,notnull"`
	BasedOnNutritionOrderID *int64    `bun:"based_on_nutrition_order_id,nullzero"`
	Notes                   *string   `bun:"notes,nullzero"`
	CreatedAt               time.Time `bun:"created_at,notnull,default:current_timestamp"`
	UpdatedAt               time.Time `bun:"updated_at,notnull,default:current_timestamp"`
	FhirNutritionIntakeID   *string   `bun:"fhir_nutrition_intake_id,unique,nullzero"`

	// 关系 (Relationships)
	User                  *User           `bun:"rel:belongs-to,join:user_id=user_id"`
	MealType              *MealType       `bun:"rel:belongs-to,join:meal_type_id=meal_type_id"`
	BasedOnNutritionOrder *NutritionOrder `bun:"rel:belongs-to,join:based_on_nutrition_order_id=order_id"`
	Items                 []*DietLogItem  `bun:"rel:has-many,join:log_id=log_id"` // 注意: Bun 可能需要调整 join 条件以适应复合主键，或依赖 log_id 上的非唯一索引
}

// DietLogItem 结构体代表 diet_log_items 表
type DietLogItem struct {
	bun.BaseModel `bun:"table:diet_log_items,alias:dli"`

	ItemID                     int64     `bun:"item_id,pk,autoincrement"`
	LogID                      int64     `bun:"log_id,notnull"`
	LogTimestamp               time.Time `bun:"log_timestamp,pk,notnull"`
	BaseProductID              int64     `bun:"base_product_id,notnull"`
	ServingQty                 float64   `bun:"serving_qty,type:numeric(10,3),notnull"`
	ServingUnitID              int32     `bun:"serving_unit_id,notnull"`
	CalculatedGramWeight       *float64  `bun:"calculated_gram_weight,type:numeric(10,2),nullzero"`
	DisplayOrder               int16     `bun:"display_order,default:0"`
	FhirConsumedItemInternalID *string   `bun:"fhir_consumed_item_internal_id,unique,nullzero"`

	// 关系 (Relationships)
	DietLog             *DietLog                         `bun:"rel:belongs-to,join:log_id=log_id"`
	BaseFoodProduct     *BaseFoodProduct                 `bun:"rel:belongs-to,join:base_product_id=base_product_id"`
	ServingUnit         *Unit                            `bun:"rel:belongs-to,join:serving_unit_id=unit_id"`
	SelectedOptions     []*FoodOption                    `bun:"m2m:diet_log_item_selected_options,join:DietLogItem=FoodOption"`
	CalculatedNutrients []*DietLogItemCalculatedNutrient `bun:"rel:has-many,join:item_id=item_id"`
}

// DietLogItemSelectedOption 结构体代表 diet_log_item_selected_options 连接表
type DietLogItemSelectedOption struct {
	bun.BaseModel `bun:"table:diet_log_item_selected_options,alias:dliso"`

	ItemID   int64 `bun:"item_id,pk"`
	OptionID int64 `bun:"option_id,pk"`
	Quantity int16 `bun:"quantity,notnull,default:1"` // 如果选项可以选择多次，取消注释

	// 关系 (Relationships)
	DietLogItem *DietLogItem `bun:"rel:belongs-to,join:item_id=item_id"`
	FoodOption  *FoodOption  `bun:"rel:belongs-to,join:option_id=option_id"`
}

// DietLogItemCalculatedNutrient 结构体代表 diet_log_item_calculated_nutrients 表
type DietLogItemCalculatedNutrient struct {
	bun.BaseModel `bun:"table:diet_log_item_calculated_nutrients,alias:dlicn"`

	CalculatedNutrientID int64   `bun:"calculated_nutrient_id,pk,autoincrement"`
	ItemID               int64   `bun:"item_id,notnull"`
	NutrientID           int32   `bun:"nutrient_id,notnull"`
	CalculatedAmount     float64 `bun:"calculated_amount,type:numeric(18,9),notnull"`
	UnitID               int32   `bun:"unit_id,notnull"`
	FhirObservationID    *string `bun:"fhir_observation_id,unique,nullzero"`

	// 关系 (Relationships)
	DietLogItem *DietLogItem `bun:"rel:belongs-to,join:item_id=item_id"`
	Nutrient    *Nutrient    `bun:"rel:belongs-to,join:nutrient_id=nutrient_id"`
	Unit        *Unit        `bun:"rel:belongs-to,join:unit_id=unit_id"`
}

// PlanDefinition 结构体代表 plan_definitions 表
type PlanDefinition struct {
	bun.BaseModel `bun:"table:plan_definitions,alias:pd"`

	PlanDefinitionID int64      `bun:"plan_definition_id,pk,autoincrement"`
	URL              *string    `bun:"url,unique,nullzero"`
	IdentifierSystem *string    `bun:"identifier_system,nullzero"`
	IdentifierValue  *string    `bun:"identifier_value,nullzero"`
	Version          *string    `bun:"version,nullzero"`
	Name             *string    `bun:"name,unique,nullzero"`
	Title            *string    `bun:"title,nullzero"`
	TypeCodeSystem   *string    `bun:"type_code_system,nullzero"`
	TypeCode         *string    `bun:"type_code,nullzero"`
	Status           string     `bun:"status,notnull"` // FHIR PublicationStatus
	Experimental     *bool      `bun:"experimental,nullzero"`
	Date             *time.Time `bun:"date,nullzero"`
	Publisher        *string    `bun:"publisher,nullzero"`
	Description      *string    `bun:"description,nullzero"`
	CreatedAt        time.Time  `bun:"created_at,notnull,default:current_timestamp"`
	UpdatedAt        time.Time  `bun:"updated_at,notnull,default:current_timestamp"`

	// 关系 (Relationships)
	Actions []*PlanDefinitionAction `bun:"rel:has-many,join:plan_definition_id=plan_definition_id"` // 一个定义有多个 Action
}

// PlanDefinitionAction 结构体代表 plan_definition_actions 表
type PlanDefinitionAction struct {
	bun.BaseModel `bun:"table:plan_definition_actions,alias:pda"`

	ActionInternalID               int64   `bun:"action_internal_id,pk,autoincrement"`
	PlanDefinitionID               int64   `bun:"plan_definition_id,notnull"`
	FhirActionID                   *string `bun:"fhir_action_id,nullzero"`
	ParentActionInternalID         *int64  `bun:"parent_action_internal_id,nullzero"`
	Prefix                         *string `bun:"prefix,nullzero"`
	Title                          *string `bun:"title,nullzero"`
	Description                    *string `bun:"description,nullzero"`
	TextEquivalent                 *string `bun:"text_equivalent,nullzero"`
	Priority                       *string `bun:"priority,nullzero"`
	DefinitionCanonicalURL         *string `bun:"definition_canonical_url,nullzero"`
	DefinitionActivityDefinitionID *int64  `bun:"definition_activity_definition_id,nullzero"` // **新增**
	TimingDescription              *string `bun:"timing_description,nullzero"`
	ConditionDescription           *string `bun:"condition_description,nullzero"`
	GroupingBehavior               *string `bun:"grouping_behavior,nullzero"`
	SelectionBehavior              *string `bun:"selection_behavior,nullzero"`
	RequiredBehavior               *string `bun:"required_behavior,nullzero"`
	PrecheckBehavior               *string `bun:"precheck_behavior,nullzero"`
	CardinalityBehavior            *string `bun:"cardinality_behavior,nullzero"`

	// 关系 (Relationships)
	PlanDefinition               *PlanDefinition                 `bun:"rel:belongs-to,join:plan_definition_id=plan_definition_id"`
	ParentAction                 *PlanDefinitionAction           `bun:"rel:belongs-to,join:parent_action_internal_id=action_internal_id"`
	ChildActions                 []*PlanDefinitionAction         `bun:"rel:has-many,join:action_internal_id=parent_action_internal_id"`
	DefinitionActivityDefinition *ActivityDefinition             `bun:"rel:belongs-to,join:definition_activity_definition_id=activity_definition_id"` // **新增**
	InstantiatedIn               []*CarePlanActivity             `bun:"rel:has-many,join:action_internal_id=instantiates_pda_internal_id"`
	RelatedActionRelations       []*PlanDefinitionActionRelation `bun:"rel:has-many,join:action_internal_id=source_action_internal_id"` // **新增**: 此 Action 定义的关系 (指向其他 Action)
	RelatedToActionRelations     []*PlanDefinitionActionRelation `bun:"rel:has-many,join:action_internal_id=target_action_internal_id"` // **新增**: 指向此 Action 的关系 (来自其他 Action)
}
type PlanDefinitionActionRelation struct {
	bun.BaseModel `bun:"table:plan_definition_action_relations,alias:pdar"`

	RelationID             int64    `bun:"relation_id,pk,autoincrement"`
	SourceActionInternalID int64    `bun:"source_action_internal_id,notnull"`
	TargetActionInternalID int64    `bun:"target_action_internal_id,notnull"`
	RelationshipType       string   `bun:"relationship_type,notnull"` // FHIR ActionRelationshipType
	OffsetDurationValue    *float64 `bun:"offset_duration_value,type:numeric(18,9),nullzero"`
	OffsetDurationUnitID   *int32   `bun:"offset_duration_unit_id,nullzero"`

	// 关系 (Relationships)
	SourceAction *PlanDefinitionAction `bun:"rel:belongs-to,join:source_action_internal_id=action_internal_id"`
	TargetAction *PlanDefinitionAction `bun:"rel:belongs-to,join:target_action_internal_id=action_internal_id"`
	OffsetUnit   *Unit                 `bun:"rel:belongs-to,join:offset_duration_unit_id=unit_id"`
}

// ========= 新增: 诊疗计划 (对应 FHIR CarePlan) =========

// CarePlan 结构体代表 care_plans 表
type CarePlan struct {
	bun.BaseModel `bun:"table:care_plans,alias:cp"`

	CarePlanID                   int64      `bun:"care_plan_id,pk,autoincrement"`
	PatientUserID                int64      `bun:"patient_user_id,notnull"`
	Status                       string     `bun:"status,notnull"` // FHIR CarePlanStatus
	Intent                       string     `bun:"intent,notnull"` // FHIR CarePlanIntent
	Title                        *string    `bun:"title,nullzero"`
	Description                  *string    `bun:"description,nullzero"`
	PeriodStartDate              *time.Time `bun:"period_start_date,nullzero"`
	PeriodEndDate                *time.Time `bun:"period_end_date,nullzero"`
	CreatedAt                    time.Time  `bun:"created_at,notnull,default:current_timestamp"`
	InstantiatesPlanDefinitionID *int64     `bun:"instantiates_plan_definition_id,nullzero"`
	FhirCareplanID               *string    `bun:"fhir_careplan_id,unique,nullzero"`

	// 关系 (Relationships)
	PatientUser         *User               `bun:"rel:belongs-to,join:patient_user_id=user_id"`
	InstantiatesPlanDef *PlanDefinition     `bun:"rel:belongs-to,join:instantiates_plan_definition_id=plan_definition_id"`
	Activities          []*CarePlanActivity `bun:"rel:has-many,join:care_plan_id=care_plan_id"` // 一个计划有多个活动
	Goals               []*UserGoal         `bun:"m2m:care_plan_goals,join:CarePlan=UserGoal"`  // 多对多: 计划关联多个目标
}

// CarePlanActivity 结构体代表 care_plan_activities 表
type CarePlanActivity struct {
	bun.BaseModel `bun:"table:care_plan_activities,alias:cpa"`

	ActivityID                       int64   `bun:"activity_id,pk,autoincrement"`
	CarePlanID                       int64   `bun:"care_plan_id,notnull"`
	InstantiatesPdaInternalID        *int64  `bun:"instantiates_pda_internal_id,nullzero"`
	InstantiatesActivityDefinitionID *int64  `bun:"instantiates_activity_definition_id,nullzero"`
	ActivityKind                     *string `bun:"activity_kind,nullzero"`
	ActivityCodeSystem               *string `bun:"activity_code_system,nullzero"`
	ActivityCode                     *string `bun:"activity_code,nullzero"`
	ActivityCodeText                 *string `bun:"activity_code_text,nullzero"`
	ActivityStatus                   string  `bun:"activity_status,notnull"`
	ReferenceResourceType            *string `bun:"reference_resource_type,nullzero"`  // 例如: 'NutritionOrder', 'UserPlanWorkout', 'ActivitySummaryObservation'
	ReferenceResourceDbID            *int64  `bun:"reference_resource_db_id,nullzero"` // 指向对应表中的数据库记录 ID
	ReferenceFhirID                  *string `bun:"reference_fhir_id,nullzero"`

	// 关系 (Relationships)
	CarePlan                       *CarePlan             `bun:"rel:belongs-to,join:care_plan_id=care_plan_id"`
	InstantiatesAction             *PlanDefinitionAction `bun:"rel:belongs-to,join:instantiates_pda_internal_id=action_internal_id"`
	InstantiatesActivityDefinition *ActivityDefinition   `bun:"rel:belongs-to,join:instantiates_activity_definition_id=activity_definition_id"`
	// 关联到具体资源的 HasOne/BelongsTo 关系需要在应用层根据 reference_resource_type 和 reference_resource_db_id 手动查询
	// 例如:
	ReferencedNutritionOrder             *NutritionOrder             `bun:"-"`
	ReferencedUserPlanWorkout            *UserPlanWorkout            `bun:"-"`
	ReferencedActivitySummaryObservation *ActivitySummaryObservation `bun:"-"`
}

// CarePlanGoal 结构体代表 care_plan_goals 连接表
type CarePlanGoal struct {
	bun.BaseModel `bun:"table:care_plan_goals,alias:cpg"`

	CarePlanID int64 `bun:"care_plan_id,pk"`
	GoalID     int64 `bun:"goal_id,pk"`

	// 关系 (Relationships)
	CarePlan *CarePlan `bun:"rel:belongs-to,join:care_plan_id=care_plan_id"`
	Goal     *UserGoal `bun:"rel:belongs-to,join:goal_id=goal_id"`
}

// ActivityDefinition 结构体代表 activity_definitions 表
// ** [修改] ** related_internal_template_workout_id 指向 UserPlanTemplateDetailWorkout
type ActivityDefinition struct {
	bun.BaseModel `bun:"table:activity_definitions,alias:ad"`

	ActivityDefinitionID             int64      `bun:"activity_definition_id,pk,autoincrement"`
	URL                              *string    `bun:"url,unique,nullzero"`
	IdentifierSystem                 *string    `bun:"identifier_system,nullzero"`
	IdentifierValue                  *string    `bun:"identifier_value,nullzero"`
	Version                          *string    `bun:"version,nullzero"`
	Name                             *string    `bun:"name,unique,nullzero"`
	Title                            *string    `bun:"title,nullzero"`
	Status                           string     `bun:"status,notnull"` // FHIR PublicationStatus
	Experimental                     *bool      `bun:"experimental,nullzero"`
	Date                             *time.Time `bun:"date,nullzero"`
	Publisher                        *string    `bun:"publisher,nullzero"`
	Description                      *string    `bun:"description,nullzero"`
	Purpose                          *string    `bun:"purpose,nullzero"`
	Usage                            *string    `bun:"usage,nullzero"`
	Kind                             *string    `bun:"kind,nullzero"` // FHIR ActivityDefinitionKind
	CodeSystem                       *string    `bun:"code_system,nullzero"`
	CodeValue                        *string    `bun:"code_value,nullzero"`
	CodeDisplay                      *string    `bun:"code_display,nullzero"`
	TimingDescription                *string    `bun:"timing_description,nullzero"`
	LocationDescription              *string    `bun:"location_description,nullzero"`
	RelatedInternalTemplateWorkoutID *int64     `bun:"related_internal_template_workout_id,nullzero"` // 指向 UserPlanTemplateDetailWorkout.ID
	CreatedAt                        time.Time  `bun:"created_at,notnull,default:current_timestamp"`
	UpdatedAt                        time.Time  `bun:"updated_at,notnull,default:current_timestamp"`

	// 关系 (Relationships)
	Targets                        []*ActivityDefinitionTarget    `bun:"rel:has-many,join:activity_definition_id=activity_definition_id"`
	RelatedInternalTemplateWorkout *UserPlanTemplateDetailWorkout `bun:"rel:belongs-to,join:related_internal_template_workout_id=id"` // **修正关系**
	// 注意: 与 PlanDefinitionAction/CarePlanActivity 的关系在对方结构体中定义 (has-many)
}

// ActivityDefinitionTarget 结构体代表 activity_definition_targets 表
type ActivityDefinitionTarget struct {
	bun.BaseModel `bun:"table:activity_definition_targets,alias:adt"`

	TargetID             int64    `bun:"target_id,pk,autoincrement"`
	ActivityDefinitionID int64    `bun:"activity_definition_id,notnull"`
	TargetType           string   `bun:"target_type,notnull"` // 'PACE', 'HEART_RATE_ZONE', etc.
	TargetValueLow       *float64 `bun:"target_value_low,type:numeric(10,3),nullzero"`
	TargetValueHigh      *float64 `bun:"target_value_high,type:numeric(10,3),nullzero"`
	TargetUnitID         *int32   `bun:"target_unit_id,nullzero"`
	TargetExpression     *string  `bun:"target_expression,nullzero"`
	Notes                *string  `bun:"notes,nullzero"`

	// 关系 (Relationships)
	ActivityDefinition *ActivityDefinition `bun:"rel:belongs-to,join:activity_definition_id=activity_definition_id"`
	TargetUnit         *Unit               `bun:"rel:belongs-to,join:target_unit_id=unit_id"`
}

// === sys_exercise_category ===

type ExerciseCategory struct {
	bun.BaseModel `bun:"table:sys_exercise_category"`
	Id            typedef.ExerciseCategory `bun:"id,pk"`
	//Id       uint16 `bun:"id,pk"`
	Key      string //"exerciseCategoryKey": "BENCH_PRESS",
	Name     string //BenchPress
	EnName   string
	CnName   string
	Exercise []*Exercise `bun:"rel:has-many,join:id=exercise_category_id"` // 运动子类型
}

type Exercise struct {
	bun.BaseModel    `bun:"table:sys_exercise"`
	Id               uint16           `bun:"id,pk"`                        // 与佳明对齐
	CategoryId       uint16           `bun:"exercise_category_id,notnull"` // 运动类型
	ExerciseCategory ExerciseCategory `bun:"rel:belongs-to,join:exercise_category_id=id"`
	Key              string           //"exerciseKey": "ALTERNATING_DUMBBELL_CHEST_PRESS",
	Name             string
	EnName           string
	CnName           string
	IsBodyWeight     bool
	// Define the M2M relationship using the junction table.
	// Filtering by 'types' happens during the query loading phase.
	PrimaryMuscles   []*Muscles `bun:"rel:m2m,m2m:sys_exercise_to_muscle,join:Exercise=Muscles"`
	SecondaryMuscles []*Muscles `bun:"rel:m2m,m2m:sys_exercise_to_muscle,join:Exercise=Muscles"`

	Equipments  []*Equipment `bun:"rel:m2m,m2m:exercise_to_equipment,join:Exercise=Equipment"` //多对多
	Counterpart []*Exercise  `bun:"m2m:exercise_to_exercise,join:Exercise=OtherExercise"`
}

// 根据 器械Equipment 和 PrimaryMuscles 肌肉查询 Exercise
func QueryExercisesByEquipmentAndMuscles(ctx context.Context, db *bun.DB, equipmentID int64, muscleID int64) ([]Exercise, error) {
	var exercises []Exercise

	err := db.NewSelect().
		Model(&exercises).
		Join("JOIN sys_exercise_to_equipment ete ON ete.exercise_id = sys_exercise.id").
		Join("JOIN sys_exercise_to_muscle etm ON etm.exercise_id = sys_exercise.id").
		Where("ete.equipment_id = ?", equipmentID).
		Where("etm.muscle_id = ?", muscleID).
		Scan(ctx)

	if err != nil {
		return nil, err
	}

	return exercises, nil
}

/**
ctx := context.Background()
	// Replace with your actual PostgreSQL DSN
	dsn := "postgres://user:pass@host:port/dbname?sslmode=disable"
	sqldb := sql.OpenDB(pgdriver.NewConnector(pgdriver.WithDSN(dsn)))
	db := bun.NewDB(sqldb, pgdialect.New())
	// db.AddQueryHook(bundebug.NewQueryHook(bundebug.WithVerbose(true))) // Enable logging

	defer db.Close()

	var exercises []Exercise
	var exerciseId uint16 = 1 // Example exercise ID to fetch

	// Fetch Exercise with ID 1, and load its Primary and Secondary muscles separately
	err := db.NewSelect().
		Model(&exercises).
		Where("id = ?", exerciseId). // Select specific exercise(s)
		Relation("PrimaryMuscles", func(q *bun.SelectQuery) *bun.SelectQuery {
			// This function modifies the query that selects from the junction table
			// Bun usually aliases the junction table with its name (e.g., "exercise_to_muscle")
			// or you can use the full table name for safety.
			return q.Where("exercise_to_muscle.types = ?", 1) // Filter for primary muscles
		}).
		Relation("SecondaryMuscles", func(q *bun.SelectQuery) *bun.SelectQuery {
			// Modify the query for the SecondaryMuscles relation
			return q.Where("exercise_to_muscle.types = ?", 2) // Filter for secondary muscles
		}).
		Scan(ctx)

	if err != nil {
		panic(err) // Handle error properly in real code
	}

	// Now 'exercises' slice contains the exercise(s) with ID 1,
	// and exercises[0].PrimaryMuscles contains only muscles where types=1
	// and exercises[0].SecondaryMuscles contains only muscles where types=2

	// You can now access them, e.g.:
	// if len(exercises) > 0 {
	//  fmt.Println("Exercise:", exercises[0].Name)
	//	fmt.Println("Primary Muscles:")
	//	for _, m := range exercises[0].PrimaryMuscles {
	//		fmt.Println("- ", m.Name)
	//	}
	//	fmt.Println("Secondary Muscles:")
	//	for _, m := range exercises[0].SecondaryMuscles {
	//		fmt.Println("- ", m.Name)
	//	}
	// }
*/

type ExerciseToExercise struct {
	bun.BaseModel   `bun:"table:sys_exercise_to_exercise"`
	ExerciseId      int64     `bun:",pk"`
	Exercise        *Exercise `bun:"rel:belongs-to,join:exercise_id=id"`
	OtherExerciseId int64     `bun:",pk"`
	OtherExercise   *Exercise `bun:"rel:belongs-to,join:other_exercise_id=id"`
}

// 器械 ，分类，动作页面查询使用
type Equipment struct {
	bun.BaseModel `bun:"table:sys_equipment"`
	Id            uint16      `bun:"id,pk"`
	Name          string      //器械名称
	Key           string      //器械名称
	EnName        string      //器械名称
	CnName        string      //器械名称
	Exercises     []*Exercise `bun:"rel:m2m:sys_exercise_to_equipment,join:Equipment=Exercise"` //多对多
}

type ExerciseToEquipments struct {
	bun.BaseModel `bun:"table:sys_exercise_to_equipment"`
	ExerciseId    int64      `bun:",pk"`
	Exercise      *Exercise  `bun:"rel:belongs-to,join:exercise_id=id"`
	EquipmentId   int64      `bun:",pk"`
	Equipment     *Equipment `bun:"rel:belongs-to,join:equipment_id=id"`
}

type Muscles struct {
	bun.BaseModel `bun:"table:sys_muscles"`
	Id            uint16 `bun:"id,pk"`
	Name          string
	Key           string
	EnName        string
	CnName        string
	Exercises     []*Exercise `bun:"rel:m2m:sys_exercise_to_muscle,join:Muscle=Exercise"` //多对多
}

type ExerciseToMuscles struct {
	bun.BaseModel `bun:"table:sys_exercise_to_muscle"`
	ExerciseId    int64     `bun:",pk"`
	Exercise      *Exercise `bun:"rel:belongs-to,join:exercise_id=id"`
	MuscleId      int64     `bun:",pk"`
	Muscle        *Muscles  `bun:"rel:belongs-to,join:muscle_id=id"`
	Types         int8      `bun:"types"` // 1:主肌肉 2:辅助肌肉 - Use capital T for exported field

}

// 推拉腿，胸肩背臀腿 ,肌肉分类 ，动作页面查询使用
type MuscleCategory struct {
	bun.BaseModel    `bun:"table:sys_muscle_category"`
	Id               int64             `bun:"id,pk,autoincrement"`
	MuscleCategoryId int64             // 上级类目 ，上胸 属于 胸类目
	MuscleCategory   []*MuscleCategory `bun:"rel:has-many,join:id=muscle_category_id"`
	Name             string            `bun:"name,unique"`
	EnName           string
	CnName           string
	Muscles          []*Muscles `bun:"m2m:sys_muscle_category_to_muscle,join:MuscleCategory=Muscles"` // 一个分类多个肌肉
}

type MuscleCategoryToMuscle struct {
	bun.BaseModel    `bun:"table:sys_muscle_category_to_muscle"`
	MuscleCategoryId int64
	MuscleCategory   *MuscleCategory `bun:"rel:belongs-to,join:muscle_category_id=id"`
	MuscleId         int64
	Muscles          *Muscles `bun:"rel:belongs-to,join:muscle_id=id"`
}

//=== sys_race_segments ===

// 赛段

/*
*
```sql

	-- 如果 PostGIS 扩展尚未启用，则启用它

CREATE EXTENSION IF NOT EXISTS postgis;

CREATE TABLE race_segments (

	id BIGSERIAL PRIMARY KEY,
	name VARCHAR(255) NOT NULL,          -- 赛段名称 (例如 "西山爬坡", "河边冲刺")
	description TEXT,                      -- 赛段描述
	activity_type VARCHAR(50) NOT NULL,   -- 适用的运动类型 (例如 'cycling', 'running')

	-- 精确定义赛段的几何路径和起终点
	defining_geom geography(LineStringZ, 4326) NOT NULL,

	-- 为了 ST_StartPoint/ST_EndPoint，将 geography 转换为 geometry,
	-- 然后将返回的 geometry 点转换回 geography
	start_point geography(PointZ, 4326) GENERATED ALWAYS AS (ST_StartPoint(defining_geom::geometry)::geography) STORED,
	end_point geography(PointZ, 4326) GENERATED ALWAYS AS (ST_EndPoint(defining_geom::geometry)::geography) STORED,

	-- 赛段的关键统计数据 (冗余存储，方便查询)
	-- ST_Length 可以直接作用于 geography 类型并返回以米为单位的长度
	total_distance_meters DOUBLE PRECISION GENERATED ALWAYS AS (ST_Length(defining_geom)) STORED,

	-- 这两个字段需要额外计算，可能通过触发器或应用程序逻辑
	elevation_gain DOUBLE PRECISION,      -- 需要从 defining_geom 计算（总爬升高度）
	average_gradient DOUBLE PRECISION,    -- 需要从 defining_geom 计算（平均坡度）

	-- 其他元数据
	created_by_user_id BIGINT,
	is_official BOOLEAN DEFAULT FALSE,
	created_at TIMESTAMPTZ DEFAULT NOW(),
	updated_at TIMESTAMPTZ DEFAULT NOW()

);

-- 可选：为提高查询性能添加空间索引
CREATE INDEX idx_race_segments_defining_geom ON race_segments USING GIST (defining_geom);
-- 可选：如果经常查询起点/终点，也可为其添加索引
-- CREATE INDEX idx_race_segments_start_point ON race_segments USING GIST (start_point);
-- CREATE INDEX idx_race_segments_end_point ON race_segments USING GIST (end_point);

	```
*/
type RaceSegment struct {
	bun.BaseModel       `bun:"table:sys_race_segments,alias:rs"`
	Id                  int64            `bun:"id,pk,autoincrement"`                                    // 主键
	Name                string           `bun:"name,notnull"`                                           // 赛段名称
	Description         *string          `bun:"description"`                                            // 赛段描述
	ActivityType        string           `bun:"activity_type,notnull"`                                  // 适用的运动类型
	DefiningGeom        *geom.LineString `bun:"defining_geom,notnull,type:geography(LineStringZ,4326)"` // 精确定义赛段的几何路径
	StartPoint          *geom.Point      `bun:"start_point,scanonly,type:geography(PointZ,4326)"`       // 起点
	EndPoint            *geom.Point      `bun:"end_point,scanonly,type:geography(PointZ,4326)"`         // 终点
	TotalDistanceMeters float64          `bun:"total_distance_meters,scanonly"`                         // 总距离
	ElevationGain       *float64         `bun:"elevation_gain"`                                         // 总爬升
	AverageGradient     *float64         `bun:"average_gradient"`                                       // 平均坡度
	CreatedByUserId     *int64           `bun:"created_by_user_id"`                                     // 创建者用户ID
	IsOfficial          bool             `bun:"is_official,default:false"`                              // 是否官方认证
	CreatedAt           time.Time        `bun:"created_at,notnull,default:current_timestamp"`           // 创建时间
	UpdatedAt           time.Time        `bun:"updated_at,notnull,default:current_timestamp"`           // 更新时间
}

/**
-- 可能还需要一个排行榜表 (Leaderboard/Efforts)
	CREATE TABLE race_segment_efforts (
	    effort_id BIGSERIAL PRIMARY KEY,
	    race_segment_id BIGINT NOT NULL REFERENCES race_segments(id) ON DELETE CASCADE,
	    user_id BIGINT NOT NULL, -- 关联用户
	    -- 关联到产生这次成绩的原始活动记录 (例如 user_routes 或 live_user_tracks 的记录ID)
	    source_activity_id BIGINT NOT NULL,
	    start_time TIMESTAMPTZ NOT NULL,     -- 通过赛段起点的时间
	    end_time TIMESTAMPTZ NOT NULL,       -- 通过赛段终点的时间
	    elapsed_time_seconds DOUBLE PRECISION NOT NULL, -- 用时 (秒，用于排名)
	    recorded_date DATE NOT NULL,        -- 记录日期
	    -- 可以冗余存储该次努力的平均功率、心率等信息
	    average_power INTEGER,
	    average_heart_rate INTEGER
	    -- 其他...
	);

	-- 排行榜查询优化索引
	CREATE INDEX idx_race_segment_efforts_leaderboard ON race_segment_efforts (race_segment_id, elapsed_time_seconds);
	CREATE INDEX idx_race_segment_efforts_user ON race_segment_efforts (user_id, race_segment_id);

*/

type RaceSegmentEffort struct {
	bun.BaseModel `bun:"table:race_segment_efforts,alias:rse"`

	EffortID           int64     `bun:"effort_id,pk,autoincrement"`   // 主键
	RaceSegmentID      int64     `bun:"race_segment_id,notnull"`      // 赛段ID
	UserID             int64     `bun:"user_id,notnull"`              // 用户ID
	SourceActivityID   int64     `bun:"source_activity_id,notnull"`   // 原始活动记录ID
	StartTime          time.Time `bun:"start_time,notnull"`           // 起点时间
	EndTime            time.Time `bun:"end_time,notnull"`             // 终点时间
	ElapsedTimeSeconds float64   `bun:"elapsed_time_seconds,notnull"` // 用时 (秒)
	RecordedDate       time.Time `bun:"recorded_date,notnull"`        // 记录日期
	AveragePower       *int      `bun:"average_power"`                // 平均功率
	AverageHeartRate   *int      `bun:"average_heart_rate"`           // 平均心率
}

//===sys_route_segment===

/**
-- 如果尚未启用 PostGIS 扩展，请启用它
CREATE EXTENSION IF NOT EXISTS postgis;

-- 可选：为受控词汇表定义 ENUM 类型
-- CREATE TYPE surface_enum AS ENUM ('paved', 'dirt', 'gravel', 'grass', 'sand', 'technical_trail', 'stairs', 'unknown'); -- 路面类型枚举
-- CREATE TYPE trail_enum AS ENUM ('official_marked', 'social_trail', 'wild_path', 'road_shoulder', 'unknown'); -- 路径类型枚举

CREATE TABLE sys_route_segments (
    segment_id BIGSERIAL PRIMARY KEY, -- 路段 ID，主键，自增

    -- 核心几何数据 (对经纬度使用 geography 类型以获得精确的米制计算)
    -- LineStringZ 存储 X, Y, Z (经度, 纬度, 海拔)
    geom geography(LineStringZ, 4326) NOT NULL, -- 几何数据，非空

    -- 预先计算的几何属性，用于更快的筛选/成本计算
    length_meters DOUBLE PRECISION GENERATED ALWAYS AS (ST_Length(geom)) STORED, -- 计算得出的长度（米）
    start_point geography(PointZ, 4326) GENERATED ALWAYS AS (ST_StartPoint(geom::geometry)) STORED, -- 计算得出的起点
    end_point geography(PointZ, 4326) GENERATED ALWAYS AS (ST_EndPoint(geom::geometry)) STORED,     -- 计算得出的终点

    -- 从源数据或分析中派生的属性 (对规划筛选/成本至关重要)
    -- 使用标准类型 (VARCHAR, BOOLEAN) 或上面定义的 ENUM
    surface_type VARCHAR(50) DEFAULT 'unknown', -- 路面类型, 例如 'paved'(铺装路), 'dirt'(土路), 'technical_trail'(技术小径), 'stairs'(台阶)
    trail_type VARCHAR(50) DEFAULT 'unknown',   -- 路径类型, 例如 'official_marked'(官方标记路径), 'wild_path'(野路)
    has_stairs BOOLEAN DEFAULT FALSE,           -- 是否有台阶的显式标志 (也可能包含在 surface_type 中)

    -- 海拔/坡度属性 (在路段创建期间计算)
    elevation_gain DOUBLE PRECISION DEFAULT 0.0, -- 总爬升
    elevation_loss DOUBLE PRECISION DEFAULT 0.0, -- 总下降
    avg_gradient DOUBLE PRECISION,              -- 平均坡度百分比 (如果平坦/无效则可为空)
    max_gradient DOUBLE PRECISION,              -- 最大上坡坡度百分比 (可为空)
    min_altitude DOUBLE PRECISION,              -- 路段最低海拔 (可为空)
    max_altitude DOUBLE PRECISION,              -- 路段最高海拔 (可为空)

    -- 数据源/置信度指标 (可选但有用)
    source_confidence DOUBLE PRECISION DEFAULT 1.0, -- 此路段数据的可靠性如何？
    source_track_count INTEGER DEFAULT 1,          -- 有多少原始轨迹贡献了此路段？

    -- 时间戳
    created_at TIMESTAMPTZ DEFAULT NOW(), -- 创建时间
    last_updated_at TIMESTAMPTZ DEFAULT NOW() -- 最后更新时间
);

-- === 索引 ===

-- 在几何数据本身上的主要空间索引 (对空间查询至关重要)
CREATE INDEX idx_sys_route_segments_geom ON sys_route_segments USING GIST (geom);

-- 可选但推荐：在生成的起点/终点上的空间索引，用于快速的路径规划起点/终点查找
-- 注意：索引生成列需要 PostgreSQL 12+
CREATE INDEX idx_sys_route_segments_start_point ON sys_route_segments USING GIST (start_point);
CREATE INDEX idx_sys_route_segments_end_point ON sys_route_segments USING GIST (end_point);


-- 在常用筛选属性上的索引
CREATE INDEX idx_sys_route_segments_surface_type ON sys_route_segments (surface_type);
CREATE INDEX idx_sys_route_segments_trail_type ON sys_route_segments (trail_type);
CREATE INDEX idx_sys_route_segments_has_stairs ON sys_route_segments (has_stairs);

-- 可选：用于在行更改时更新 last_updated_at 的触发器
CREATE OR REPLACE FUNCTION update_modified_column()
RETURNS TRIGGER AS $$
BEGIN
    NEW.last_updated_at = NOW();
    RETURN NEW;
END;
$$ language 'plpgsql';

CREATE TRIGGER update_route_segments_modtime
BEFORE UPDATE ON sys_route_segments
FOR EACH ROW
EXECUTE FUNCTION update_modified_column();
*/

// RouteSegment 代表已清洗的 route_segments 表中的一行数据。
type RouteSegment struct {
	bun.BaseModel `bun:"table:sys_route_segments,alias:srs"` // 定义表名和别名

	SegmentID int64 `bun:"segment_id,pk,autoincrement"` // 路段ID, 主键, 自增

	// --- 几何数据 ---
	// 如果 geom 列理论上可能为 NULL，则使用指针，否则使用非指针类型
	// 在 tag 中精确匹配数据库类型
	Geom *geom.LineString `bun:"geom,notnull,type:geography(LineStringZ, 4326)"` // 几何数据，非空

	// --- 生成的几何属性 ---
	// 如果这些列在数据库中是 GENERATED ALWAYS，则在 bun 中将它们标记为只读
	// Bun 可能需要特殊处理或在插入/更新时忽略这些列
	LengthMeters float64     `bun:"length_meters,scanonly"`                            // 长度(米), 从数据库只读
	StartPoint   *geom.Point `bun:"start_point,scanonly,type:geography(PointZ, 4326)"` // 起点, 只读
	EndPoint     *geom.Point `bun:"end_point,scanonly,type:geography(PointZ, 4326)"`   // 终点, 只读

	// --- 用于筛选/成本计算的属性 ---
	SurfaceType *string `bun:"surface_type"` // 路面类型, 指针用于处理潜在的 NULL/默认值
	TrailType   *string `bun:"trail_type"`   // 路径类型
	HasStairs   *bool   `bun:"has_stairs"`   // 是否有台阶, 如果列可为空，使用指针区分 false 和 NULL

	// --- 海拔/坡度属性 ---
	ElevationGain float64  `bun:"elevation_gain"` // 总爬升
	ElevationLoss float64  `bun:"elevation_loss"` // 总下降
	AvgGradient   *float64 `bun:"avg_gradient"`   // 平均坡度, 指针因为可能为 NULL
	MaxGradient   *float64 `bun:"max_gradient"`   // 最大上坡坡度
	MinAltitude   *float64 `bun:"min_altitude"`   // 最低海拔
	MaxAltitude   *float64 `bun:"max_altitude"`   // 最高海拔

	// --- 数据源/置信度 ---
	SourceConfidence *float64 `bun:"source_confidence"`  // 数据置信度
	SourceTrackCount int      `bun:"source_track_count"` // 来源轨迹数量

	// --- 时间戳 ---
	CreatedAt     time.Time `bun:"created_at,notnull,default:current_timestamp"`      // 创建时间
	LastUpdatedAt time.Time `bun:"last_updated_at,notnull,default:current_timestamp"` // 最后更新时间
}

// 关于生成列 (`scanonly`) 的说明:
// `bun:",scanonly"` 标签告诉 Bun 从数据库读取此值，但在 INSERT 或 UPDATE 操作中不包含它，
// 这对于 GENERATED 列是正确的。如果不使用生成列，请移除 `,scanonly` 并在插入前在 Go 中计算这些值。

// 关于 go-geom 的说明:
// 你需要确保 Bun 和你的数据库驱动（例如 pgdriver）已配置为能够正确地序列化和反序列化
// go-geom 类型（如 geom.LineString, geom.Point）与数据库使用的 PostGIS WKB
// (Well-Known Binary) 或 EWKB 格式之间的转换。
// 这可能涉及自定义类型处理或使用 Bun 扩展（如果可用）。

//=== sys_sport===

type Sport struct {
	bun.BaseModel   `bun:"table:sys_sports"`
	Id              int64 //SportId*1000+SubSportId
	SportId         typedef.Sport
	SportName       string
	SportEnName     string
	SportCnName     string
	SubSportId      typedef.SubSport
	SubSportName    string
	SubSportEnName  string
	SubSportCnName  string
	SportCategories []*SportCategory `bun:"rel:m2m,m2m:sys_sport_category_to_sport,join:Sport=SportCategory"`
}

type SportCategory struct {
	bun.BaseModel       `bun:"table:sys_sport_category"`
	Id                  uint8
	SportCategoryName   string
	SportCategoryEnName string
	SportCategoryCnName string
	SportCategoryKey    string
	Sports              []*Sport `bun:"rel:m2m,m2m:sys_sport_category_to_sport,join:SportCategory=Sport"` // 运动子类型
}

type SportCategoryToSport struct {
	bun.BaseModel   `bun:"table:sys_sport_category_to_sport"`
	Id              int64 `bun:"id,pk,autoincrement"`
	SportCategoryId uint8
	SportCategory   *SportCategory `bun:"rel:belongs-to,join:sport_category_id=id"`
	SportId         int64
	Sport           *Sport `bun:"rel:belongs-to,join:sport_id=id"`
}

// === uer_fit_activity ===
type MsgActivity struct {
	bun.BaseModel  `bun:"table:msg_activity"`
	Id             int64 `bun:"id,pk,autoincrement"`
	UserActivityId int64 `bun:"user_activity_id"`
	Timestamp      time.Time
	LocalTimestamp time.Time // timestamp epoch expressed in local time, used to convert activity timestamps to local time
	TotalTimerTime uint32    // Scale: 1000; Units: s; Exclude pauses
	NumSessions    uint16
	Type           typedef.Activity
	Event          typedef.Event
	EventType      typedef.EventType
	EventGroup     uint8

	UnknownFields   []proto.Field          `bun:",jsonb"` // UnknownFields are fields that are exist but they are not defined in Profile.xlsx
	DeveloperFields []proto.DeveloperField `bun:",jsonb"` // DeveloperFields are custom data fields [Added since protocol version 2.0]
}

type UserActivitySummary struct {
	bun.BaseModel     `bun:"table:user_activity"`
	Id                int64          `bun:"id,pk,autoincrement"`
	FitFileId         mesgdef.FileId `bun:",jsonb"`
	FileId            string
	UserId            int64
	TimeCreated       time.Time // Only set for files that are can be created/erased.
	ProductName       string    // Optional free form string to indicate the devices name or model
	SerialNumber      uint32    // Base: uint32z
	Manufacturer      typedef.Manufacturer
	Product           uint16
	Number            uint16 // Only set for files that are not created/erased.
	Type              typedef.File
	DeveloperDataIds  []*mesgdef.DeveloperDataId  `bun:",jsonb"` //jsonb
	FieldDescriptions []*mesgdef.FieldDescription `bun:",jsonb"`

	Activity *MsgActivity  `bun:"rel:has-one,join:id=user_activity_id"`
	Sessions []*MsgSession `bun:"rel:has-many,join:id=user_activity_id"`
	Laps     []*MsgLap     `bun:"rel:has-many,join:id=user_activity_id"`

	UnrelatedMessages []proto.Message `bun:",jsonb"`
}

/*
*
  - 运动记录 应该是fit解析后的数据

https://developer.garmin.com/fit/protocol/
*/
type UserActivity struct { // 运动记录 某次运动,
	UserActivitySummary

	Records []*MsgRecord `bun:"rel:has-many,join:id=user_activity_id"`
	Sets    []*MsgSet    `bun:"rel:has-many,join:id=user_activity_id"`

	// Optional Messages
	UserProfileId  int64                  // 这个动作的介绍
	UserProfile    *UserProfile           `bun:"rel:belongs-to,join:user_profile_id=id"`
	DeviceInfos    []*mesgdef.DeviceInfo  `bun:",jsonb"` // required fields: timestamp
	Events         []*Event               `bun:"rel:has-many,join:id=user_activity_id"`
	Lengths        []*Length              `bun:"rel:has-many,join:id=user_activity_id"` // required fields: timestamp, event, event_type
	SegmentLaps    []*SegmentLap          `bun:"rel:has-many,join:id=user_activity_id"`
	ZonesTargets   []*ZonesTarget         `bun:"rel:has-many,join:id=user_activity_id"`
	Workouts       []*mesgdef.Workout     `bun:",jsonb"`
	WorkoutSteps   []*mesgdef.WorkoutStep `bun:",jsonb"`
	HRs            []*MsgHr               `bun:"rel:has-many,join:id=user_activity_id"`
	HRVs           []*Hrv                 `bun:"rel:has-many,join:id=user_activity_id"` // required fields: time
	GpsMetadatas   []*GpsMetadata         `bun:"rel:has-many,join:id=user_activity_id"`
	TimeInZones    []*TimeInZone          `bun:"rel:has-many,join:id=user_activity_id"`
	Splits         []*Split               `bun:"rel:has-many,join:id=user_activity_id"`
	SplitSummaries []*SplitSummary        `bun:"rel:has-many,join:id=user_activity_id"`                      // entries must be unique within each split_type
	Sports         []*Sport               `bun:"m2m:user_activity_sports_relevancy,join:UserActivity=Sport"` // 一个Activity多个运动
}

type UserActivitySportRelevancy struct {
	bun.BaseModel  `bun:"table:user_activity_sports_relevancy"`
	UserActivityId int64         `bun:",pk"`
	UserActivity   *UserActivity `bun:"rel:belongs-to,join:user_activity_id=id"`
	SportId        int64         `bun:",pk"`
	Sport          *Sport        `bun:"rel:belongs-to,join:sport_id=id"`
}

// === uer_msg===
type UserProfile struct {
	bun.BaseModel              `bun:"table:user_msg_user_profile"`
	Id                         int64                    `bun:"id,pk,autoincrement"`
	FriendlyName               string                   // Used for Morning Report greeting
	WakeTime                   typedef.LocaltimeIntoDay // Typical wake time
	SleepTime                  typedef.LocaltimeIntoDay // Typical bed time
	DiveCount                  uint32
	GlobalIdString             string
	GlobalId                   [6]byte `bun:",array"` // Array: [6]
	MessageIndex               typedef.MessageIndex
	Weight                     uint16 // Scale: 10; Units: kg
	LocalId                    typedef.UserLocalId
	UserRunningStepLength      uint16 // Scale: 1000; Units: m; User defined running step length set to 0 for auto length
	UserWalkingStepLength      uint16 // Scale: 1000; Units: m; User defined walking step length set to 0 for auto length
	Gender                     typedef.Gender
	Age                        uint8 // Units: years
	Height                     uint8 // Scale: 100; Units: m
	Language                   typedef.Language
	ElevSetting                typedef.DisplayMeasure
	WeightSetting              typedef.DisplayMeasure
	RestingHeartRate           uint8 // Units: bpm
	DefaultMaxRunningHeartRate uint8 // Units: bpm
	DefaultMaxBikingHeartRate  uint8 // Units: bpm
	DefaultMaxHeartRate        uint8 // Units: bpm
	HrSetting                  typedef.DisplayHeart
	SpeedSetting               typedef.DisplayMeasure
	DistSetting                typedef.DisplayMeasure
	PowerSetting               typedef.DisplayPower
	ActivityClass              typedef.ActivityClass
	PositionSetting            typedef.DisplayPosition
	TemperatureSetting         typedef.DisplayMeasure
	HeightSetting              typedef.DisplayMeasure
	DepthSetting               typedef.DisplayMeasure
}

type ZonesTarget struct {
	bun.BaseModel            `bun:"table:msg_zones_target"`
	Id                       int64 `bun:"id,pk,autoincrement"`
	UserActivityId           int64 `bun:"user_activity_id"`
	FunctionalThresholdPower uint16
	MaxHeartRate             uint8
	ThresholdHeartRate       uint8
	HrCalcType               typedef.HrZoneCalc
	PwrCalcType              typedef.PwrZoneCalc
}
type TimeInZone struct {
	bun.BaseModel            `bun:"table:msg_time_in_zone"`
	UserActivityId           int64     `bun:"pk,user_activity_id"`
	Timestamp                time.Time `bun:"pk,"`
	TimeInHrZone             []uint32  `bun:",array"` // Array: [N]; Scale: 1000; Units: s
	TimeInSpeedZone          []uint32  `bun:",array"` // Array: [N]; Scale: 1000; Units: s
	TimeInCadenceZone        []uint32  `bun:",array"` // Array: [N]; Scale: 1000; Units: s
	TimeInPowerZone          []uint32  `bun:",array"` // Array: [N]; Scale: 1000; Units: s
	HrZoneHighBoundary       []uint8   `bun:",array"` // Array: [N]; Units: bpm
	SpeedZoneHighBoundary    []uint16  `bun:",array"` // Array: [N]; Scale: 1000; Units: m/s
	CadenceZoneHighBoundary  []uint8   `bun:",array"` // Array: [N]; Units: rpm
	PowerZoneHighBoundary    []uint16  `bun:",array"` // Array: [N]; Units: watts
	ReferenceMesg            typedef.MesgNum
	ReferenceIndex           typedef.MessageIndex
	FunctionalThresholdPower uint16
	HrCalcType               typedef.HrZoneCalc
	MaxHeartRate             uint8
	RestingHeartRate         uint8
	ThresholdHeartRate       uint8
	PwrCalcType              typedef.PwrZoneCalc
}

type MsgHr struct {
	bun.BaseModel       `bun:"table:msg_hr"`
	UserActivityId      int64     `bun:"pk,user_activity_id"`
	Timestamp           time.Time `bun:"pk,"`
	FilteredBpm         []uint8   `bun:",array"` // Array: [N]; Units: bpm
	EventTimestamp      []uint32  `bun:",array"` // Array: [N]; Scale: 1024; Units: s
	EventTimestamp12    []byte    `bun:",array"` // Array: [N]; Units: s
	FractionalTimestamp uint16    // Scale: 32768; Units: s
	Time256             uint8     // Scale: 256; Units: s

}

type Hrv struct {
	bun.BaseModel  `bun:"table:msg_hrv"`
	Id             int64    `bun:"id,pk,autoincrement"`
	UserActivityId int64    `bun:"user_activity_id"`
	Time           []uint16 `bun:",array"` // Array: [N]; Scale: 1000; Units: s; Time between beats

}

type GpsMetadata struct {
	bun.BaseModel    `bun:"table:msg_gps_metadata"`
	UserActivityId   int64     `bun:"pk,user_activity_id"`
	Timestamp        time.Time `bun:"pk,"`
	UtcTimestamp     time.Time // Units: s; Used to correlate UTC to system time if the timestamp of the message is in system time. This UTC time is derived from the GPS data.
	PositionLat      int32     // Units: semicircles
	PositionLong     int32     // Units: semicircles
	EnhancedAltitude uint32    // Scale: 5; Offset: 500; Units: m
	EnhancedSpeed    uint32    // Scale: 1000; Units: m/s
	Velocity         [3]int16  `bun:",array"` // Array: [3]; Scale: 100; Units: m/s; velocity[0] is lon velocity. Velocity[1] is lat velocity. Velocity[2] is altitude velocity.
	TimestampMs      uint16    // Units: ms; Millisecond part of the timestamp.
	Heading          uint16    // Scale: 100; Units: degrees

}

type Split struct {
	bun.BaseModel     `bun:"table:msg_split"`
	UserActivityId    int64     `bun:"pk,user_activity_id"`
	StartTime         time.Time `bun:"pk,"`
	EndTime           time.Time
	TotalElapsedTime  uint32 // Scale: 1000; Units: s
	TotalTimerTime    uint32 // Scale: 1000; Units: s
	TotalDistance     uint32 // Scale: 100; Units: m
	AvgSpeed          uint32 // Scale: 1000; Units: m/s
	StartPositionLat  int32  // Units: semicircles
	StartPositionLong int32  // Units: semicircles
	EndPositionLat    int32  // Units: semicircles
	EndPositionLong   int32  // Units: semicircles
	MaxSpeed          uint32 // Scale: 1000; Units: m/s
	AvgVertSpeed      int32  // Scale: 1000; Units: m/s
	TotalCalories     uint32 // Units: kcal
	StartElevation    uint32 // Scale: 5; Offset: 500; Units: m
	TotalMovingTime   uint32 // Scale: 1000; Units: s
	MessageIndex      typedef.MessageIndex
	TotalAscent       uint16 // Units: m
	TotalDescent      uint16 // Units: m
	SplitType         typedef.SplitType
}

type SplitSummary struct {
	bun.BaseModel   `bun:"table:msg_split_summary"`
	Id              int64  `bun:"id,pk,autoincrement"`
	UserActivityId  int64  `bun:"user_activity_id"`
	TotalTimerTime  uint32 // Scale: 1000; Units: s
	TotalDistance   uint32 // Scale: 100; Units: m
	AvgSpeed        uint32 // Scale: 1000; Units: m/s
	MaxSpeed        uint32 // Scale: 1000; Units: m/s
	AvgVertSpeed    int32  // Scale: 1000; Units: m/s
	TotalCalories   uint32 // Units: kcal
	TotalMovingTime uint32 // Scale: 1000; Units: s
	MessageIndex    typedef.MessageIndex
	NumSplits       uint16
	TotalAscent     uint16 // Units: m
	TotalDescent    uint16 // Units: m
	SplitType       typedef.SplitType
	AvgHeartRate    uint8 // Units: bpm
	MaxHeartRate    uint8 // Units: bpm

}

type Event struct {
	bun.BaseModel               `bun:"table:msg_event"`
	UserActivityId              int64     `bun:"pk,user_activity_id"`
	Timestamp                   time.Time `bun:"pk,"`
	StartTimestamp              time.Time // Units: s; Timestamp of when the event started
	Data                        uint32
	Data16                      uint16
	Score                       uint16 // Do not populate directly. Autogenerated by decoder for sport_point subfield components
	OpponentScore               uint16 // Do not populate directly. Autogenerated by decoder for sport_point subfield components
	Event                       typedef.Event
	EventType                   typedef.EventType
	EventGroup                  uint8
	FrontGearNum                uint8 // Base: uint8z; Do not populate directly. Autogenerated by decoder for gear_change subfield components. Front gear number. 1 is innermost.
	FrontGear                   uint8 // Base: uint8z; Do not populate directly. Autogenerated by decoder for gear_change subfield components. Number of front teeth.
	RearGearNum                 uint8 // Base: uint8z; Do not populate directly. Autogenerated by decoder for gear_change subfield components. Rear gear number. 1 is innermost.
	RearGear                    uint8 // Base: uint8z; Do not populate directly. Autogenerated by decoder for gear_change subfield components. Number of rear teeth.
	DeviceIndex                 typedef.DeviceIndex
	ActivityType                typedef.ActivityType         // Activity Type associated with an auto_activity_detect event
	RadarThreatLevelMax         typedef.RadarThreatLevelType // Do not populate directly. Autogenerated by decoder for threat_alert subfield components.
	RadarThreatCount            uint8                        // Do not populate directly. Autogenerated by decoder for threat_alert subfield components.
	RadarThreatAvgApproachSpeed uint8                        // Scale: 10; Units: m/s; Do not populate directly. Autogenerated by decoder for radar_threat_alert subfield components
	RadarThreatMaxApproachSpeed uint8                        // Scale: 10; Units: m/s; Do not populate directly. Autogenerated by decoder for radar_threat_alert subfield components

	state [4]uint8 `bun:",array"` // Used for tracking expanded fields.

}

type Length struct {
	bun.BaseModel              `bun:"table:msg_length"`
	UserActivityId             int64     `bun:"pk,user_activity_id"`
	Timestamp                  time.Time `bun:"pk,"`
	StartTime                  time.Time
	StrokeCount                []uint16 `bun:",array"` // Array: [N]; Units: counts; stroke_type enum used as the index
	ZoneCount                  []uint16 `bun:",array"` // Array: [N]; Units: counts; zone number used as the index
	TotalElapsedTime           uint32   // Scale: 1000; Units: s
	TotalTimerTime             uint32   // Scale: 1000; Units: s
	MessageIndex               typedef.MessageIndex
	TotalStrokes               uint16 // Units: strokes
	AvgSpeed                   uint16 // Scale: 1000; Units: m/s
	TotalCalories              uint16 // Units: kcal
	PlayerScore                uint16
	OpponentScore              uint16
	EnhancedAvgRespirationRate uint16 // Scale: 100; Units: Breaths/min
	EnhancedMaxRespirationRate uint16 // Scale: 100; Units: Breaths/min
	Event                      typedef.Event
	EventType                  typedef.EventType
	SwimStroke                 typedef.SwimStroke // Units: swim_stroke
	AvgSwimmingCadence         uint8              // Units: strokes/min
	EventGroup                 uint8
	LengthType                 typedef.LengthType
	AvgRespirationRate         uint8
	MaxRespirationRate         uint8

	state [4]uint8 `bun:",array"` // Used for tracking expanded fields.

	UnknownFields   []proto.Field          `bun:",jsonb"` // UnknownFields are fields that are exist but they are not defined in Profile.xlsx
	DeveloperFields []proto.DeveloperField `bun:",jsonb"` // DeveloperFields are custom data fields [Added since protocol version 2.0]
}

type SegmentLap struct {
	bun.BaseModel               `bun:"table:msg_segment_lap"`
	UserActivityId              int64     `bun:"pk,user_activity_id"`
	Timestamp                   time.Time `bun:"pk,"`
	StartTime                   time.Time
	Name                        string
	TimeInHrZone                []uint32 `bun:",array"` // Array: [N]; Scale: 1000; Units: s
	TimeInSpeedZone             []uint32 `bun:",array"` // Array: [N]; Scale: 1000; Units: s
	TimeInCadenceZone           []uint32 `bun:",array"` // Array: [N]; Scale: 1000; Units: s
	TimeInPowerZone             []uint32 `bun:",array"` // Array: [N]; Scale: 1000; Units: s
	Uuid                        string
	AvgLeftPowerPhase           []uint8  `bun:",array"` // Array: [N]; Scale: 0.7111111; Units: degrees; Average left power phase angles. Data value indexes defined by power_phase_type.
	AvgLeftPowerPhasePeak       []uint8  `bun:",array"` // Array: [N]; Scale: 0.7111111; Units: degrees; Average left power phase peak angles. Data value indexes defined by power_phase_type.
	AvgRightPowerPhase          []uint8  `bun:",array"` // Array: [N]; Scale: 0.7111111; Units: degrees; Average right power phase angles. Data value indexes defined by power_phase_type.
	AvgRightPowerPhasePeak      []uint8  `bun:",array"` // Array: [N]; Scale: 0.7111111; Units: degrees; Average right power phase peak angles. Data value indexes defined by power_phase_type.
	AvgPowerPosition            []uint16 `bun:",array"` // Array: [N]; Units: watts; Average power by position. Data value indexes defined by rider_position_type.
	MaxPowerPosition            []uint16 `bun:",array"` // Array: [N]; Units: watts; Maximum power by position. Data value indexes defined by rider_position_type.
	AvgCadencePosition          []uint8  `bun:",array"` // Array: [N]; Units: rpm; Average cadence by position. Data value indexes defined by rider_position_type.
	MaxCadencePosition          []uint8  `bun:",array"` // Array: [N]; Units: rpm; Maximum cadence by position. Data value indexes defined by rider_position_type.
	StartPositionLat            int32    // Units: semicircles
	StartPositionLong           int32    // Units: semicircles
	EndPositionLat              int32    // Units: semicircles
	EndPositionLong             int32    // Units: semicircles
	TotalElapsedTime            uint32   // Scale: 1000; Units: s; Time (includes pauses)
	TotalTimerTime              uint32   // Scale: 1000; Units: s; Timer Time (excludes pauses)
	TotalDistance               uint32   // Scale: 100; Units: m
	TotalCycles                 uint32   // Units: cycles
	NecLat                      int32    // Units: semicircles; North east corner latitude.
	NecLong                     int32    // Units: semicircles; North east corner longitude.
	SwcLat                      int32    // Units: semicircles; South west corner latitude.
	SwcLong                     int32    // Units: semicircles; South west corner latitude.
	TotalWork                   uint32   // Units: J
	TotalMovingTime             uint32   // Scale: 1000; Units: s
	ActiveTime                  uint32   // Scale: 1000; Units: s
	TimeStanding                uint32   // Scale: 1000; Units: s; Total time spent in the standing position
	TotalGrit                   float32  // Units: kGrit; The grit score estimates how challenging a route could be for a cyclist in terms of time spent going over sharp turns or large grade slopes.
	TotalFlow                   float32  // Units: Flow; The flow score estimates how long distance wise a cyclist deaccelerates over intervals where deacceleration is unnecessary such as smooth turns or small grade angle intervals.
	AvgGrit                     float32  // Units: kGrit; The grit score estimates how challenging a route could be for a cyclist in terms of time spent going over sharp turns or large grade slopes.
	AvgFlow                     float32  // Units: Flow; The flow score estimates how long distance wise a cyclist deaccelerates over intervals where deacceleration is unnecessary such as smooth turns or small grade angle intervals.
	EnhancedAvgAltitude         uint32   // Scale: 5; Offset: 500; Units: m
	EnhancedMaxAltitude         uint32   // Scale: 5; Offset: 500; Units: m
	EnhancedMinAltitude         uint32   // Scale: 5; Offset: 500; Units: m
	MessageIndex                typedef.MessageIndex
	TotalCalories               uint16 // Units: kcal
	TotalFatCalories            uint16 // Units: kcal; If New Leaf
	AvgSpeed                    uint16 // Scale: 1000; Units: m/s
	MaxSpeed                    uint16 // Scale: 1000; Units: m/s
	AvgPower                    uint16 // Units: watts; total_power / total_timer_time if non_zero_avg_power otherwise total_power / total_elapsed_time
	MaxPower                    uint16 // Units: watts
	TotalAscent                 uint16 // Units: m
	TotalDescent                uint16 // Units: m
	NormalizedPower             uint16 // Units: watts
	LeftRightBalance            typedef.LeftRightBalance100
	AvgAltitude                 uint16 // Scale: 5; Offset: 500; Units: m
	MaxAltitude                 uint16 // Scale: 5; Offset: 500; Units: m
	AvgGrade                    int16  // Scale: 100; Units: %
	AvgPosGrade                 int16  // Scale: 100; Units: %
	AvgNegGrade                 int16  // Scale: 100; Units: %
	MaxPosGrade                 int16  // Scale: 100; Units: %
	MaxNegGrade                 int16  // Scale: 100; Units: %
	AvgPosVerticalSpeed         int16  // Scale: 1000; Units: m/s
	AvgNegVerticalSpeed         int16  // Scale: 1000; Units: m/s
	MaxPosVerticalSpeed         int16  // Scale: 1000; Units: m/s
	MaxNegVerticalSpeed         int16  // Scale: 1000; Units: m/s
	RepetitionNum               uint16
	MinAltitude                 uint16 // Scale: 5; Offset: 500; Units: m
	WktStepIndex                typedef.MessageIndex
	FrontGearShiftCount         uint16
	RearGearShiftCount          uint16
	StandCount                  uint16               // Number of transitions to the standing state
	Manufacturer                typedef.Manufacturer // Manufacturer that produced the segment
	Event                       typedef.Event
	EventType                   typedef.EventType
	AvgHeartRate                uint8 // Units: bpm
	MaxHeartRate                uint8 // Units: bpm
	AvgCadence                  uint8 // Units: rpm; total_cycles / total_timer_time if non_zero_avg_cadence otherwise total_cycles / total_elapsed_time
	MaxCadence                  uint8 // Units: rpm
	Sport                       typedef.Sport
	EventGroup                  uint8
	SubSport                    typedef.SubSport
	GpsAccuracy                 uint8 // Units: m
	AvgTemperature              int8  // Units: C
	MaxTemperature              int8  // Units: C
	MinHeartRate                uint8 // Units: bpm
	SportEvent                  typedef.SportEvent
	AvgLeftTorqueEffectiveness  uint8 // Scale: 2; Units: percent
	AvgRightTorqueEffectiveness uint8 // Scale: 2; Units: percent
	AvgLeftPedalSmoothness      uint8 // Scale: 2; Units: percent
	AvgRightPedalSmoothness     uint8 // Scale: 2; Units: percent
	AvgCombinedPedalSmoothness  uint8 // Scale: 2; Units: percent
	Status                      typedef.SegmentLapStatus
	AvgFractionalCadence        uint8 // Scale: 128; Units: rpm; fractional part of the avg_cadence
	MaxFractionalCadence        uint8 // Scale: 128; Units: rpm; fractional part of the max_cadence
	TotalFractionalCycles       uint8 // Scale: 128; Units: cycles; fractional part of the total_cycles
	AvgLeftPco                  int8  // Units: mm; Average left platform center offset
	AvgRightPco                 int8  // Units: mm; Average right platform center offset
	TotalFractionalAscent       uint8 // Scale: 100; Units: m; fractional part of total_ascent
	TotalFractionalDescent      uint8 // Scale: 100; Units: m; fractional part of total_descent

	state [12]uint8 `bun:",array"` // Used for tracking expanded fields.

	UnknownFields   []proto.Field          `bun:",jsonb"` // UnknownFields are fields that are exist but they are not defined in Profile.xlsx
	DeveloperFields []proto.DeveloperField `bun:",jsonb"` // DeveloperFields are custom data fields [Added since protocol version 2.0]
}

type MsgLap struct {
	bun.BaseModel                 `bun:"table:msg_lap"`
	UserActivityId                int64     `bun:"pk,user_activity_id"`
	Timestamp                     time.Time `bun:"pk,"`
	StartTime                     time.Time
	TimeInHrZone                  []uint32 `bun:",array"` // Array: [N]; Scale: 1000; Units: s
	TimeInSpeedZone               []uint32 `bun:",array"` // Array: [N]; Scale: 1000; Units: s
	TimeInCadenceZone             []uint32 `bun:",array"` // Array: [N]; Scale: 1000; Units: s
	TimeInPowerZone               []uint32 `bun:",array"` // Array: [N]; Scale: 1000; Units: s
	StrokeCount                   []uint16 `bun:",array"` // Array: [N]; Units: counts; stroke_type enum used as the index
	ZoneCount                     []uint16 `bun:",array"` // Array: [N]; Units: counts; zone number used as the index
	AvgTotalHemoglobinConc        []uint16 `bun:",array"` // Array: [N]; Scale: 100; Units: g/dL; Avg saturated and unsaturated hemoglobin
	MinTotalHemoglobinConc        []uint16 `bun:",array"` // Array: [N]; Scale: 100; Units: g/dL; Min saturated and unsaturated hemoglobin
	MaxTotalHemoglobinConc        []uint16 `bun:",array"` // Array: [N]; Scale: 100; Units: g/dL; Max saturated and unsaturated hemoglobin
	AvgSaturatedHemoglobinPercent []uint16 `bun:",array"` // Array: [N]; Scale: 10; Units: %; Avg percentage of hemoglobin saturated with oxygen
	MinSaturatedHemoglobinPercent []uint16 `bun:",array"` // Array: [N]; Scale: 10; Units: %; Min percentage of hemoglobin saturated with oxygen
	MaxSaturatedHemoglobinPercent []uint16 `bun:",array"` // Array: [N]; Scale: 10; Units: %; Max percentage of hemoglobin saturated with oxygen
	AvgLeftPowerPhase             []uint8  // Array: [N]; Scale: 0.7111111; Units: degrees; Average left power phase angles. Data value indexes defined by power_phase_type.
	AvgLeftPowerPhasePeak         []uint8  // Array: [N]; Scale: 0.7111111; Units: degrees; Average left power phase peak angles. Data value indexes defined by power_phase_type.
	AvgRightPowerPhase            []uint8  // Array: [N]; Scale: 0.7111111; Units: degrees; Average right power phase angles. Data value indexes defined by power_phase_type.
	AvgRightPowerPhasePeak        []uint8  // Array: [N]; Scale: 0.7111111; Units: degrees; Average right power phase peak angles. Data value indexes defined by power_phase_type.
	AvgPowerPosition              []uint16 `bun:",array"` // Array: [N]; Units: watts; Average power by position. Data value indexes defined by rider_position_type.
	MaxPowerPosition              []uint16 `bun:",array"` // Array: [N]; Units: watts; Maximum power by position. Data value indexes defined by rider_position_type.
	AvgCadencePosition            []uint8  `bun:",array"` // Array: [N]; Units: rpm; Average cadence by position. Data value indexes defined by rider_position_type.
	MaxCadencePosition            []uint8  `bun:",array"` // Array: [N]; Units: rpm; Maximum cadence by position. Data value indexes defined by rider_position_type.
	StartPositionLat              int32    // Units: semicircles
	StartPositionLong             int32    // Units: semicircles
	EndPositionLat                int32    // Units: semicircles
	EndPositionLong               int32    // Units: semicircles
	TotalElapsedTime              uint32   // Scale: 1000; Units: s; Time (includes pauses)
	TotalTimerTime                uint32   // Scale: 1000; Units: s; Timer Time (excludes pauses)
	TotalDistance                 uint32   // Scale: 100; Units: m
	TotalCycles                   uint32   // Units: cycles
	TotalWork                     uint32   // Units: J
	TotalMovingTime               uint32   // Scale: 1000; Units: s
	TimeStanding                  uint32   // Scale: 1000; Units: s; Total time spent in the standing position
	EnhancedAvgSpeed              uint32   // Scale: 1000; Units: m/s
	EnhancedMaxSpeed              uint32   // Scale: 1000; Units: m/s
	EnhancedAvgAltitude           uint32   // Scale: 5; Offset: 500; Units: m
	EnhancedMinAltitude           uint32   // Scale: 5; Offset: 500; Units: m
	EnhancedMaxAltitude           uint32   // Scale: 5; Offset: 500; Units: m
	AvgDepth                      uint32   // Scale: 1000; Units: m; 0 if above water
	MaxDepth                      uint32   // Scale: 1000; Units: m; 0 if above water
	TotalGrit                     float32  // Units: kGrit; The grit score estimates how challenging a route could be for a cyclist in terms of time spent going over sharp turns or large grade slopes.
	TotalFlow                     float32  // Units: Flow; The flow score estimates how long distance wise a cyclist deaccelerates over intervals where deacceleration is unnecessary such as smooth turns or small grade angle intervals.
	AvgGrit                       float32  // Units: kGrit; The grit score estimates how challenging a route could be for a cyclist in terms of time spent going over sharp turns or large grade slopes.
	AvgFlow                       float32  // Units: Flow; The flow score estimates how long distance wise a cyclist deaccelerates over intervals where deacceleration is unnecessary such as smooth turns or small grade angle intervals.
	MessageIndex                  typedef.MessageIndex
	TotalCalories                 uint16 // Units: kcal
	TotalFatCalories              uint16 // Units: kcal; If New Leaf
	AvgSpeed                      uint16 // Scale: 1000; Units: m/s
	MaxSpeed                      uint16 // Scale: 1000; Units: m/s
	AvgPower                      uint16 // Units: watts; total_power / total_timer_time if non_zero_avg_power otherwise total_power / total_elapsed_time
	MaxPower                      uint16 // Units: watts
	TotalAscent                   uint16 // Units: m
	TotalDescent                  uint16 // Units: m
	NumLengths                    uint16 // Units: lengths; # of lengths of swim pool
	NormalizedPower               uint16 // Units: watts
	LeftRightBalance              typedef.LeftRightBalance100
	FirstLengthIndex              uint16
	AvgStrokeDistance             uint16 // Scale: 100; Units: m
	NumActiveLengths              uint16 // Units: lengths; # of active lengths of swim pool
	AvgAltitude                   uint16 // Scale: 5; Offset: 500; Units: m
	MaxAltitude                   uint16 // Scale: 5; Offset: 500; Units: m
	AvgGrade                      int16  // Scale: 100; Units: %
	AvgPosGrade                   int16  // Scale: 100; Units: %
	AvgNegGrade                   int16  // Scale: 100; Units: %
	MaxPosGrade                   int16  // Scale: 100; Units: %
	MaxNegGrade                   int16  // Scale: 100; Units: %
	AvgPosVerticalSpeed           int16  // Scale: 1000; Units: m/s
	AvgNegVerticalSpeed           int16  // Scale: 1000; Units: m/s
	MaxPosVerticalSpeed           int16  // Scale: 1000; Units: m/s
	MaxNegVerticalSpeed           int16  // Scale: 1000; Units: m/s
	RepetitionNum                 uint16
	MinAltitude                   uint16 // Scale: 5; Offset: 500; Units: m
	WktStepIndex                  typedef.MessageIndex
	OpponentScore                 uint16
	AvgVerticalOscillation        uint16 // Scale: 10; Units: mm
	AvgStanceTimePercent          uint16 // Scale: 100; Units: percent
	AvgStanceTime                 uint16 // Scale: 10; Units: ms
	PlayerScore                   uint16
	StandCount                    uint16 // Number of transitions to the standing state
	AvgLevMotorPower              uint16 // Units: watts; lev average motor power during lap
	MaxLevMotorPower              uint16 // Units: watts; lev maximum motor power during lap
	AvgVerticalRatio              uint16 // Scale: 100; Units: percent
	AvgStanceTimeBalance          uint16 // Scale: 100; Units: percent
	AvgStepLength                 uint16 // Scale: 10; Units: mm
	AvgVam                        uint16 // Scale: 1000; Units: m/s
	EnhancedAvgRespirationRate    uint16 // Scale: 100; Units: Breaths/min
	EnhancedMaxRespirationRate    uint16 // Scale: 100; Units: Breaths/min
	JumpCount                     uint16
	AvgCoreTemperature            uint16 // Scale: 100; Units: C
	MinCoreTemperature            uint16 // Scale: 100; Units: C
	MaxCoreTemperature            uint16 // Scale: 100; Units: C
	Event                         typedef.Event
	EventType                     typedef.EventType
	AvgHeartRate                  uint8 // Units: bpm
	MaxHeartRate                  uint8 // Units: bpm
	AvgCadence                    uint8 // Units: rpm; total_cycles / total_timer_time if non_zero_avg_cadence otherwise total_cycles / total_elapsed_time
	MaxCadence                    uint8 // Units: rpm
	Intensity                     typedef.Intensity
	LapTrigger                    typedef.LapTrigger
	Sport                         typedef.Sport
	EventGroup                    uint8
	SwimStroke                    typedef.SwimStroke
	SubSport                      typedef.SubSport
	GpsAccuracy                   uint8 // Units: m
	AvgTemperature                int8  // Units: C
	MaxTemperature                int8  // Units: C
	MinHeartRate                  uint8 // Units: bpm
	AvgFractionalCadence          uint8 // Scale: 128; Units: rpm; fractional part of the avg_cadence
	MaxFractionalCadence          uint8 // Scale: 128; Units: rpm; fractional part of the max_cadence
	TotalFractionalCycles         uint8 // Scale: 128; Units: cycles; fractional part of the total_cycles
	AvgLeftTorqueEffectiveness    uint8 // Scale: 2; Units: percent
	AvgRightTorqueEffectiveness   uint8 // Scale: 2; Units: percent
	AvgLeftPedalSmoothness        uint8 // Scale: 2; Units: percent
	AvgRightPedalSmoothness       uint8 // Scale: 2; Units: percent
	AvgCombinedPedalSmoothness    uint8 // Scale: 2; Units: percent
	AvgLeftPco                    int8  // Units: mm; Average left platform center offset
	AvgRightPco                   int8  // Units: mm; Average right platform center offset
	LevBatteryConsumption         uint8 // Scale: 2; Units: percent; lev battery consumption during lap
	MinTemperature                int8  // Units: C
	AvgRespirationRate            uint8
	MaxRespirationRate            uint8
	TotalFractionalAscent         uint8 // Scale: 100; Units: m; fractional part of total_ascent
	TotalFractionalDescent        uint8 // Scale: 100; Units: m; fractional part of total_descent

	state [18]uint8 `bun:",array"` // Used for tracking expanded fields.

	UnknownFields   []proto.Field          `bun:",jsonb"` // UnknownFields are fields that are exist but they are not defined in Profile.xlsx
	DeveloperFields []proto.DeveloperField `bun:",jsonb"` // DeveloperFields are custom data fields [Added since protocol version 2.0]
}

//=== user_msg_record ===

type MsgRecord struct {
	bun.BaseModel                 `bun:"table:msg_record"`
	UserActivityId                int64                    `bun:"pk,user_activity_id"`
	Timestamp                     time.Time                `bun:"pk,"`    // 时间戳，单位：秒
	Speed1S                       []uint8                  `bun:",array"` // 1秒间隔的速度，数组：[N]；比例：16；单位：米/秒；时间戳字段表示最后一个数组元素的时间
	LeftPowerPhase                []uint8                  `bun:",array"` // 左功率相位角，数组：[N]；比例：0.7111111；单位：度；数据值索引由power_phase_type定义
	LeftPowerPhasePeak            []uint8                  `bun:",array"` // 左功率相位峰值角，数组：[N]；比例：0.7111111；单位：度；数据值索引由power_phase_type定义
	RightPowerPhase               []uint8                  `bun:",array"` // 右功率相位角，数组：[N]；比例：0.7111111；单位：度；数据值索引由power_phase_type定义
	RightPowerPhasePeak           []uint8                  `bun:",array"` // 右功率相位峰值角，数组：[N]；比例：0.7111111；单位：度；数据值索引由power_phase_type定义
	PositionLat                   int32                    // 纬度，单位：半圆
	PositionLong                  int32                    // 经度，单位：半圆
	Altitude                      uint16                   // 海拔，比例：5；偏移量：500；单位：米
	Location                      *geom.Point              `bun:"location,notnull,type:geography(PointZ, 4326)"`
	Distance                      uint32                   // 距离，比例：100；单位：米
	TimeFromCourse                int32                    // 偏离路线的时间，比例：1000；单位：秒
	TotalCycles                   uint32                   // 总循环次数，单位：循环
	AccumulatedPower              uint32                   // 累积功率，单位：瓦特
	EnhancedSpeed                 uint32                   // 增强速度，比例：1000；单位：米/秒
	EnhancedAltitude              uint32                   // 经过气压计校准的海拔，比例：5；偏移量：500；单位：米
	AbsolutePressure              uint32                   // 绝对压力，单位：帕；包括大气压力
	Depth                         uint32                   // 深度，比例：1000；单位：米；如果在水上则为0
	NextStopDepth                 uint32                   // 下一停靠深度，比例：1000；单位：米；如果在水上则为0
	NextStopTime                  uint32                   // 下一停靠时间，单位：秒
	TimeToSurface                 uint32                   // 到达水面的时间，单位：秒
	NdlTime                       uint32                   // 无减压极限时间，单位：秒
	Grit                          float32                  // 粗糙度分数，估计骑行者在急转弯或大坡度斜坡上花费的时间
	Flow                          float32                  // 流动分数，估计骑行者在不必要的减速区间（如平滑转弯或小坡度区间）内的减速距离
	AirTimeRemaining              uint32                   // 剩余空气时间，单位：秒
	AscentRate                    int32                    // 上升率，比例：1000；单位：米/秒
	Speed                         uint16                   // 速度，比例：1000；单位：米/秒
	Power                         uint16                   // 功率，单位：瓦特
	Grade                         int16                    // 坡度，比例：100；单位：百分比
	CompressedAccumulatedPower    uint16                   // 压缩累积功率，单位：瓦特
	VerticalSpeed                 int16                    // 垂直速度，比例：1000；单位：米/秒
	Calories                      uint16                   // 卡路里，单位：千卡
	VerticalOscillation           uint16                   // 垂直振荡，比例：10；单位：毫米
	StanceTimePercent             uint16                   // 站立时间百分比，比例：100；单位：百分比
	StanceTime                    uint16                   // 站立时间，比例：10；单位：毫秒
	BallSpeed                     uint16                   // 球速，比例：100；单位：米/秒
	Cadence256                    uint16                   // 踏频256，比例：256；单位：转/分钟；记录踏频和分数踏频以向后兼容
	TotalHemoglobinConc           uint16                   // 总血红蛋白浓度，比例：100；单位：克/分升；总饱和和未饱和血红蛋白
	TotalHemoglobinConcMin        uint16                   // 最小总血红蛋白浓度，比例：100；单位：克/分升；最小饱和和未饱和血红蛋白
	TotalHemoglobinConcMax        uint16                   // 最大总血红蛋白浓度，比例：100；单位：克/分升；最大饱和和未饱和血红蛋白
	SaturatedHemoglobinPercent    uint16                   // 饱和血红蛋白百分比，比例：10；单位：百分比；氧饱和血红蛋白的百分比
	SaturatedHemoglobinPercentMin uint16                   // 最小饱和血红蛋白百分比，比例：10；单位：百分比；最小氧饱和血红蛋白的百分比
	SaturatedHemoglobinPercentMax uint16                   // 最大饱和血红蛋白百分比，比例：10；单位：百分比；最大氧饱和血红蛋白的百分比
	MotorPower                    uint16                   // 电机功率，单位：瓦特；电动助力车电机功率
	VerticalRatio                 uint16                   // 垂直比率，比例：100；单位：百分比
	StanceTimeBalance             uint16                   // 站立时间平衡，比例：100；单位：百分比
	StepLength                    uint16                   // 步长，比例：10；单位：毫米
	CycleLength16                 uint16                   // 循环长度16，比例：100；单位：米；支持划船运动所需的更大循环尺寸。最大循环尺寸：655.35
	N2Load                        uint16                   // 氮负荷，单位：百分比
	EnhancedRespirationRate       uint16                   // 增强呼吸频率，比例：100；单位：呼吸/分钟
	CurrentStress                 uint16                   // 当前压力，比例：100；当前压力值
	EbikeTravelRange              uint16                   // 电动助力车行驶范围，单位：公里
	PressureSac                   uint16                   // 压力表面空气消耗，比例：100；单位：巴/分钟
	VolumeSac                     uint16                   // 体积表面空气消耗，比例：100；单位：升/分钟
	Rmv                           uint16                   // 呼吸分钟量，比例：100；单位：升/分钟
	CoreTemperature               uint16                   // 核心温度，比例：100；单位：摄氏度
	CompressedSpeedDistance       [3]byte                  `bun:",array"` // 压缩速度距离，数组：[3]；单位：米/秒，米
	HeartRate                     uint8                    // 心率，单位：次/分钟
	Cadence                       uint8                    // 踏频，单位：转/分钟
	Resistance                    uint8                    // 阻力，相对值。0表示无，254表示最大
	CycleLength                   uint8                    // 循环长度，比例：100；单位：米
	Temperature                   int8                     // 温度，单位：摄氏度
	Cycles                        uint8                    // 循环次数，单位：循环
	LeftRightBalance              typedef.LeftRightBalance // 左右平衡
	GpsAccuracy                   uint8                    // GPS精度，单位：米
	ActivityType                  typedef.ActivityType     // 活动类型
	LeftTorqueEffectiveness       uint8                    // 左扭矩效率，比例：2；单位：百分比
	RightTorqueEffectiveness      uint8                    // 右扭矩效率，比例：2；单位：百分比
	LeftPedalSmoothness           uint8                    // 左踏板平滑度，比例：2；单位：百分比
	RightPedalSmoothness          uint8                    // 右踏板平滑度，比例：2；单位：百分比
	CombinedPedalSmoothness       uint8                    // 综合踏板平滑度，比例：2；单位：百分比
	Time128                       uint8                    // 时间128，比例：128；单位：秒
	StrokeType                    typedef.StrokeType       // 划水类型
	Zone                          uint8                    // 区域
	FractionalCadence             uint8                    // 分数踏频，比例：128；单位：转/分钟
	DeviceIndex                   typedef.DeviceIndex      // 设备索引
	LeftPco                       int8                     // 左平台中心偏移，单位：毫米
	RightPco                      int8                     // 右平台中心偏移，单位：毫米
	BatterySoc                    uint8                    // 电池状态，比例：2；单位：百分比；电动助力车电池电量
	CnsLoad                       uint8                    // 中枢神经系统负荷，单位：百分比
	RespirationRate               uint8                    // 呼吸频率，单位：秒
	EbikeBatteryLevel             uint8                    // 电动助力车电池电量，单位：百分比
	EbikeAssistMode               uint8                    // 电动助力车助力模式，单位：取决于传感器
	EbikeAssistLevelPercent       uint8                    // 电动助力车助力水平百分比，单位：百分比
	Po2                           uint8                    // 氧分压，比例：100；单位：百分比；当前氧分压
	state                         [14]uint8                `bun:",array"` // Used for tracking expanded fields.

	UnknownFields   []proto.Field          `bun:",jsonb"` // UnknownFields are fields that are exist but they are not defined in Profile.xlsx
	DeveloperFields []proto.DeveloperField `bun:",jsonb"` // DeveloperFields are custom data fields [Added since protocol version 2.0]

}

//type TrackPoint struct {
//	bun.BaseModel `bun:"table:track_points,alias:tp"`
//
//	ActivityID         int64       `bun:"activity_id,notnull"` // 通常作为复合主键/分区键一部分
//	Timestamp          time.Time   `bun:"timestamp,notnull"`   // 通常作为复合主键/时间分区键
//	Location           *geom.Point `bun:"location,notnull,type:geography(PointZ, 4326)"`
//	HeartRate          *int        `bun:"heart_rate"` // 使用指针或 sql.NullInt types 表示可空
//	Power              *int        `bun:"power"`
//	Cadence            *int        `bun:"cadence"`
//	SpeedMPS           *float64    `bun:"speed_mps"`
//	Temperature        *float64    `bun:"temperature"`
//	HorizontalAccuracy *float64    `bun:"horizontal_accuracy"`
//	VerticalAccuracy   *float64    `bun:"vertical_accuracy"`
//
//	// 注意: Bun 对于没有单一主键的 TimescaleDB 超表可能需要特定配置或处理方式。
//	// 复合主键可以用 `bun:",pk"` 标记在多个字段上。
//}

type MsgSet struct {
	bun.BaseModel     `bun:"table:msg_set"`
	UserActivityId    int64                      `bun:"pk,user_activity_id"`
	Timestamp         time.Time                  `bun:"pk,"` // 时间戳，单位：秒
	StartTime         time.Time                  // Start time of the set
	Category          []typedef.ExerciseCategory `bun:",array"` // Array: [N]
	CategorySubtype   []uint16                   `bun:",array"` // Array: [N]; Based on the associated category, see [category]_exercise_names
	LocalCategoryId   []uint16                   `bun:",array"`
	Duration          uint32                     // Scale: 1000; Units: s
	Repetitions       uint16                     // # of repitions of the movement
	Weight            uint16                     // Scale: 16; Units: kg; Amount of weight applied for the set
	WeightDisplayUnit typedef.FitBaseUnit
	MessageIndex      typedef.MessageIndex
	WktStepIndex      typedef.MessageIndex
	SetType           typedef.SetType

	UnknownFields   []proto.Field          `bun:",jsonb"` // UnknownFields are fields that are exist but they are not defined in Profile.xlsx
	DeveloperFields []proto.DeveloperField `bun:",jsonb"` // DeveloperFields are custom data fields [Added since protocol version 2.0]
}

// == uer_msg_session ==
type MsgSession struct {
	bun.BaseModel                 `bun:"table:msg_session"`
	Id                            int64     `bun:"id,pk,autoincrement"`
	UserActivityId                int64     `bun:"user_activity_id"`
	Timestamp                     time.Time // Units: s; Sesson end time.
	StartTime                     time.Time
	TimeInHrZone                  []uint32 `bun:",array"` // Array: [N]; Scale: 1000; Units: s
	TimeInSpeedZone               []uint32 `bun:",array"` // Array: [N]; Scale: 1000; Units: s
	TimeInCadenceZone             []uint32 `bun:",array"` // Array: [N]; Scale: 1000; Units: s
	TimeInPowerZone               []uint32 `bun:",array"` // Array: [N]; Scale: 1000; Units: s
	OpponentName                  string
	StrokeCount                   []uint16 `bun:",array"` // Array: [N]; Units: counts; stroke_type enum used as the index
	ZoneCount                     []uint16 `bun:",array"` // Array: [N]; Units: counts; zone number used as the index
	AvgTotalHemoglobinConc        []uint16 `bun:",array"` // Array: [N]; Scale: 100; Units: g/dL; Avg saturated and unsaturated hemoglobin
	MinTotalHemoglobinConc        []uint16 `bun:",array"` // Array: [N]; Scale: 100; Units: g/dL; Min saturated and unsaturated hemoglobin
	MaxTotalHemoglobinConc        []uint16 `bun:",array"` // Array: [N]; Scale: 100; Units: g/dL; Max saturated and unsaturated hemoglobin
	AvgSaturatedHemoglobinPercent []uint16 `bun:",array"` // Array: [N]; Scale: 10; Units: %; Avg percentage of hemoglobin saturated with oxygen
	MinSaturatedHemoglobinPercent []uint16 `bun:",array"` // Array: [N]; Scale: 10; Units: %; Min percentage of hemoglobin saturated with oxygen
	MaxSaturatedHemoglobinPercent []uint16 `bun:",array"` // Array: [N]; Scale: 10; Units: %; Max percentage of hemoglobin saturated with oxygen
	SportProfileName              string   // Sport name from associated sport mesg
	AvgLeftPowerPhase             []uint8  `bun:",array"` // Array: [N]; Scale: 0.7111111; Units: degrees; Average left power phase angles. Indexes defined by power_phase_type.
	AvgLeftPowerPhasePeak         []uint8  `bun:",array"` // Array: [N]; Scale: 0.7111111; Units: degrees; Average left power phase peak angles. Data value indexes defined by power_phase_type.
	AvgRightPowerPhase            []uint8  `bun:",array"` // Array: [N]; Scale: 0.7111111; Units: degrees; Average right power phase angles. Data value indexes defined by power_phase_type.
	AvgRightPowerPhasePeak        []uint8  `bun:",array"` // Array: [N]; Scale: 0.7111111; Units: degrees; Average right power phase peak angles data value indexes defined by power_phase_type.
	AvgPowerPosition              []uint16 `bun:",array"` // Array: [N]; Units: watts; Average power by position. Data value indexes defined by rider_position_type.
	MaxPowerPosition              []uint16 `bun:",array"` // Array: [N]; Units: watts; Maximum power by position. Data value indexes defined by rider_position_type.
	AvgCadencePosition            []uint8  `bun:",array"` // Array: [N]; Units: rpm; Average cadence by position. Data value indexes defined by rider_position_type.
	MaxCadencePosition            []uint8  `bun:",array"` // Array: [N]; Units: rpm; Maximum cadence by position. Data value indexes defined by rider_position_type.
	StartPositionLat              int32    // Units: semicircles
	StartPositionLong             int32    // Units: semicircles
	TotalElapsedTime              uint32   // Scale: 1000; Units: s; Time (includes pauses)
	TotalTimerTime                uint32   // Scale: 1000; Units: s; Timer Time (excludes pauses)
	TotalDistance                 uint32   // Scale: 100; Units: m
	TotalCycles                   uint32   // Units: cycles
	NecLat                        int32    // Units: semicircles; North east corner latitude
	NecLong                       int32    // Units: semicircles; North east corner longitude
	SwcLat                        int32    // Units: semicircles; South west corner latitude
	SwcLong                       int32    // Units: semicircles; South west corner longitude
	EndPositionLat                int32    // Units: semicircles
	EndPositionLong               int32    // Units: semicircles
	AvgStrokeCount                uint32   // Scale: 10; Units: strokes/lap
	TotalWork                     uint32   // Units: J
	TotalMovingTime               uint32   // Scale: 1000; Units: s
	AvgLapTime                    uint32   // Scale: 1000; Units: s
	TimeStanding                  uint32   // Scale: 1000; Units: s; Total time spend in the standing position
	EnhancedAvgSpeed              uint32   // Scale: 1000; Units: m/s; total_distance / total_timer_time
	EnhancedMaxSpeed              uint32   // Scale: 1000; Units: m/s
	EnhancedAvgAltitude           uint32   // Scale: 5; Offset: 500; Units: m
	EnhancedMinAltitude           uint32   // Scale: 5; Offset: 500; Units: m
	EnhancedMaxAltitude           uint32   // Scale: 5; Offset: 500; Units: m
	AvgDepth                      uint32   // Scale: 1000; Units: m; 0 if above water
	MaxDepth                      uint32   // Scale: 1000; Units: m; 0 if above water
	SurfaceInterval               uint32   // Units: s; Time since end of last dive
	DiveNumber                    uint32
	TrainingLoadPeak              int32                // Scale: 65536
	TotalGrit                     float32              // Units: kGrit; The grit score estimates how challenging a route could be for a cyclist in terms of time spent going over sharp turns or large grade slopes.
	TotalFlow                     float32              // Units: Flow; The flow score estimates how long distance wise a cyclist deaccelerates over intervals where deacceleration is unnecessary such as smooth turns or small grade angle intervals.
	AvgGrit                       float32              // Units: kGrit; The grit score estimates how challenging a route could be for a cyclist in terms of time spent going over sharp turns or large grade slopes.
	AvgFlow                       float32              // Units: Flow; The flow score estimates how long distance wise a cyclist deaccelerates over intervals where deacceleration is unnecessary such as smooth turns or small grade angle intervals.
	MessageIndex                  typedef.MessageIndex // Selected bit is set for the current session.
	TotalCalories                 uint16               // Units: kcal
	TotalFatCalories              uint16               // Units: kcal
	AvgSpeed                      uint16               // Scale: 1000; Units: m/s; total_distance / total_timer_time
	MaxSpeed                      uint16               // Scale: 1000; Units: m/s
	AvgPower                      uint16               // Units: watts; total_power / total_timer_time if non_zero_avg_power otherwise total_power / total_elapsed_time
	MaxPower                      uint16               // Units: watts
	TotalAscent                   uint16               // Units: m
	TotalDescent                  uint16               // Units: m
	FirstLapIndex                 uint16
	NumLaps                       uint16
	NumLengths                    uint16 // Units: lengths; # of lengths of swim pool
	NormalizedPower               uint16 // Units: watts
	TrainingStressScore           uint16 // Scale: 10; Units: tss
	IntensityFactor               uint16 // Scale: 1000; Units: if
	LeftRightBalance              typedef.LeftRightBalance100
	AvgStrokeDistance             uint16 // Scale: 100; Units: m
	PoolLength                    uint16 // Scale: 100; Units: m
	ThresholdPower                uint16 // Units: watts
	NumActiveLengths              uint16 // Units: lengths; # of active lengths of swim pool
	AvgAltitude                   uint16 // Scale: 5; Offset: 500; Units: m
	MaxAltitude                   uint16 // Scale: 5; Offset: 500; Units: m
	AvgGrade                      int16  // Scale: 100; Units: %
	AvgPosGrade                   int16  // Scale: 100; Units: %
	AvgNegGrade                   int16  // Scale: 100; Units: %
	MaxPosGrade                   int16  // Scale: 100; Units: %
	MaxNegGrade                   int16  // Scale: 100; Units: %
	AvgPosVerticalSpeed           int16  // Scale: 1000; Units: m/s
	AvgNegVerticalSpeed           int16  // Scale: 1000; Units: m/s
	MaxPosVerticalSpeed           int16  // Scale: 1000; Units: m/s
	MaxNegVerticalSpeed           int16  // Scale: 1000; Units: m/s
	BestLapIndex                  uint16
	MinAltitude                   uint16 // Scale: 5; Offset: 500; Units: m
	PlayerScore                   uint16
	OpponentScore                 uint16
	MaxBallSpeed                  uint16 // Scale: 100; Units: m/s
	AvgBallSpeed                  uint16 // Scale: 100; Units: m/s
	AvgVerticalOscillation        uint16 // Scale: 10; Units: mm
	AvgStanceTimePercent          uint16 // Scale: 100; Units: percent
	AvgStanceTime                 uint16 // Scale: 10; Units: ms
	StandCount                    uint16 // Number of transitions to the standing state
	AvgLevMotorPower              uint16 // Units: watts; lev average motor power during session
	MaxLevMotorPower              uint16 // Units: watts; lev maximum motor power during session
	AvgVerticalRatio              uint16 // Scale: 100; Units: percent
	AvgStanceTimeBalance          uint16 // Scale: 100; Units: percent
	AvgStepLength                 uint16 // Scale: 10; Units: mm
	AvgVam                        uint16 // Scale: 1000; Units: m/s
	StartN2                       uint16 // Units: percent
	EndN2                         uint16 // Units: percent
	O2Toxicity                    uint16 // Units: OTUs
	EnhancedAvgRespirationRate    uint16 // Scale: 100; Units: Breaths/min
	EnhancedMaxRespirationRate    uint16 // Scale: 100; Units: Breaths/min
	EnhancedMinRespirationRate    uint16 // Scale: 100
	JumpCount                     uint16
	AvgCoreTemperature            uint16            // Scale: 100; Units: C
	MinCoreTemperature            uint16            // Scale: 100; Units: C
	MaxCoreTemperature            uint16            // Scale: 100; Units: C
	Event                         typedef.Event     // session
	EventType                     typedef.EventType // stop
	Sport                         typedef.Sport
	SubSport                      typedef.SubSport
	AvgHeartRate                  uint8 // Units: bpm; average heart rate (excludes pause time)
	MaxHeartRate                  uint8 // Units: bpm
	AvgCadence                    uint8 // Units: rpm; total_cycles / total_timer_time if non_zero_avg_cadence otherwise total_cycles / total_elapsed_time
	MaxCadence                    uint8 // Units: rpm
	TotalTrainingEffect           uint8 // Scale: 10
	EventGroup                    uint8
	Trigger                       typedef.SessionTrigger
	SwimStroke                    typedef.SwimStroke // Units: swim_stroke
	PoolLengthUnit                typedef.DisplayMeasure
	GpsAccuracy                   uint8 // Units: m
	AvgTemperature                int8  // Units: C
	MaxTemperature                int8  // Units: C
	MinHeartRate                  uint8 // Units: bpm
	AvgFractionalCadence          uint8 // Scale: 128; Units: rpm; fractional part of the avg_cadence
	MaxFractionalCadence          uint8 // Scale: 128; Units: rpm; fractional part of the max_cadence
	TotalFractionalCycles         uint8 // Scale: 128; Units: cycles; fractional part of the total_cycles
	AvgLeftTorqueEffectiveness    uint8 // Scale: 2; Units: percent
	AvgRightTorqueEffectiveness   uint8 // Scale: 2; Units: percent
	AvgLeftPedalSmoothness        uint8 // Scale: 2; Units: percent
	AvgRightPedalSmoothness       uint8 // Scale: 2; Units: percent
	AvgCombinedPedalSmoothness    uint8 // Scale: 2; Units: percent
	SportIndex                    uint8
	AvgLeftPco                    int8  // Units: mm; Average platform center offset Left
	AvgRightPco                   int8  // Units: mm; Average platform center offset Right
	LevBatteryConsumption         uint8 // Scale: 2; Units: percent; lev battery consumption during session
	TotalAnaerobicTrainingEffect  uint8 // Scale: 10
	StartCns                      uint8 // Units: percent
	EndCns                        uint8 // Units: percent
	AvgRespirationRate            uint8
	MaxRespirationRate            uint8
	MinRespirationRate            uint8
	MinTemperature                int8  // Units: C
	WorkoutFeel                   uint8 // A 0-100 scale representing how a user felt while performing a workout. Low values are considered feeling bad, while high values are good.
	WorkoutRpe                    uint8 // Common Borg CR10 / 0-10 RPE scale, multiplied 10x.. Aggregate score for all workouts in a single session.
	AvgSpo2                       uint8 // Units: percent; Average SPO2 for the monitoring session
	AvgStress                     uint8 // Units: percent; Average stress for the monitoring session
	SdrrHrv                       uint8 // Units: mS; Standard deviation of R-R interval (SDRR) - Heart rate variability measure most useful for wellness users.
	RmssdHrv                      uint8 // Units: mS; Root mean square successive difference (RMSSD) - Heart rate variability measure most useful for athletes
	TotalFractionalAscent         uint8 // Scale: 100; Units: m; fractional part of total_ascent
	TotalFractionalDescent        uint8 // Scale: 100; Units: m; fractional part of total_descent

	state [23]uint8 `bun:",array"` // Used for tracking expanded fields.

	UnknownFields   []proto.Field          `bun:",jsonb"` // UnknownFields are fields that are exist but they are not defined in Profile.xlsx
	DeveloperFields []proto.DeveloperField `bun:",jsonb"` // DeveloperFields are custom data fields [Added since protocol version 2.0]
}

//==== user_routes

// 用户自己做的路书
type RouteBook struct {
	bun.BaseModel `bun:"table:user_road_book"`
	Id            int64   `bun:"id,pk,autoincrement"`
	UserId        int64   `bun:"user_id,notnull"` // 用户ID
	Name          *string `bun:"name"`            // 名称，指针表示可为空
	Description   *string `bun:"description"`     // 描述
	// 完整的路线几何
	Geom *geom.LineString `bun:"geom,notnull,type:geography(LineStringZ, 4326)"`
	// 预计算或用户提供的元数据
	TotalDistanceMeters *float64 `bun:"total_distance_meters"` // 总距离
	TotalElevationGain  *float64 `bun:"total_elevation_gain"`  // 总爬升
	TotalElevationLoss  *float64 `bun:"total_elevation_loss"`  // 总下降

	IsPublic bool `bun:"is_public,default:false"` // 是否公开

	// 时间戳
	CreatedAt time.Time `bun:"created_at,notnull,default:current_timestamp"`
	UpdatedAt time.Time `bun:"updated_at,notnull,default:current_timestamp"`
}

//=== user_workout ===

// UserPlan 根据 PlanTemplate 生成，每个周期生成。也根据日期 放假等调整
// Deprecated
type UserPlan struct {
	bun.BaseModel `bun:"table:user_plan"`
	Id            int64 `bun:"id,pk,autoincrement"`
	UserId        int64
	Name          int64
	Date          time.Time     // 某一天的
	Completed     bool          // TRUE if this activity has been started
	CycleLength   int           //周期总天数
	CycleDay      int           // 第几天
	PlanDetail    []*PlanDetail `bun:"rel:has-many,join:id=plan_id"`
}

// Deprecated
type PlanDetail struct { // 第几天
	bun.BaseModel         `bun:"table:user_plan_detail"`
	Id                    int64 `bun:"id,pk,autoincrement"`
	PlanId                int64
	CycleDay              int                    // 第几天
	PlanDetailDietaryDate *PlanDetailDietaryDate `bun:"rel:has-one,join:id=plan_detail_id"`
	PlanDetailDietaries   []*PlanDetailDietary   `bun:"rel:has-many,join:id=plan_detail_id"`
	PlanDetailWorkouts    []*UserPlanWorkout     `bun:"rel:has-many,join:id=plan_detail_id"`
}

// Deprecated
type PlanDetailDietaryDate struct { // 某天， 计划吃多少
	bun.BaseModel          `bun:"table:user_plan_detail_dietary"`
	Id                     int64   `bun:"id,pk,autoincrement"`
	PlanDetailId           int64   `bun:"plan_detail_id"`
	CarbohydrateMultiplier float64 // 体重倍数
	ProteinMultiplier      float64 // 体重倍数
	FatMultiplier          float64 // 体重倍数
	Carbohydrate           float64 // g数
	Protein                float64 // g数
	Fat                    float64 // g数
	Kcal                   float64
	Kj                     float64
}

// Deprecated
type PlanDetailDietary struct { // 某天，某次 计划吃多少
	bun.BaseModel          `bun:"table:user_plan_detail_dietary"`
	Id                     int64   `bun:"id,pk,autoincrement"`
	PlanDetailId           int64   `bun:"plan_detail_id"`
	CarbohydrateMultiplier float64 // 体重倍数
	ProteinMultiplier      float64 // 体重倍数
	FatMultiplier          float64 // 体重倍数
	Carbohydrate           float64 // g数
	Protein                float64 // g数
	Fat                    float64 // g数
	Kcal                   float64
	Kj                     float64
	// 第几餐
	SortOrder               int                        // 排序
	PlanDetailFoodRelations []*PlanDetailFoodRelations `bun:"rel:has-many,join:id=plan_detail_dietary_id"`
}

// Deprecated
type PlanDetailFoodRelations struct { // 按菜谱吃，按计划吃，具体怎么吃
	bun.BaseModel       `bun:"table:user_plan_detail_food_relations"`
	Id                  int64 `bun:"id,pk,autoincrement"`
	PlanDetailDietaryId int64 `bun:"plan_detail_dietary_id"`
	FoodId              int64 `bun:"food_id,notnull"`
	MenuId              int64
	Weight              float64 // 克数
}

type UserPlanWorkout struct {
	bun.BaseModel                `bun:"table:user_plan_workout"`
	Id                           int64          `bun:"id,pk,autoincrement"`
	PlanDetailId                 int64          `bun:"plan_detail_id"`
	FitFileId                    mesgdef.FileId `bun:",jsonb"`
	FileId                       string
	WktName                      string
	WktDescription               string                      // Description of the workout
	Capabilities                 typedef.WorkoutCapabilities `bun:"-"` // Base: uint32z
	CapabilitiesInterval         bool
	CapabilitiesCustom           bool
	CapabilitiesFitnessEquipment bool
	CapabilitiesFirstbeat        bool
	CapabilitiesNewLeaf          bool
	CapabilitiesTcx              bool
	CapabilitiesSpeed            bool
	CapabilitiesHeartRate        bool
	CapabilitiesDistance         bool
	CapabilitiesCadence          bool
	CapabilitiesPower            bool
	CapabilitiesGrade            bool
	CapabilitiesResistance       bool
	CapabilitiesProtected        bool
	MessageIndex                 typedef.MessageIndex //uint16
	NumValidSteps                uint16               // number of valid steps
	PoolLength                   uint16               // Scale: 100; Units: m
	//Sport typedef.Sport
	//SubSport typedef.SubSport
	SportId         int64
	Sport           *Sport `bun:"rel:belongs-to,join:sport_id=id"`
	PoolLengthUnit  typedef.DisplayMeasure
	SortOrder       int
	UnknownFields   []proto.Field          `bun:",jsonb"` // UnknownFields are fields that are exist but they are not defined in Profile.xlsx
	DeveloperFields []proto.DeveloperField `bun:",jsonb"` // DeveloperFields are custom data fields [Added since protocol version 2.0]

	WorkoutSteps []*PlanDetailWorkoutStep `bun:"rel:has-many,join:id=plan_detail_workout_id"`
}

type PlanDetailWorkoutStep struct {
	bun.BaseModel                  `bun:"table:user_plan_detail_workout_step"`
	Id                             int64 `bun:"id,pk,autoincrement"`
	WktStepName                    string
	Notes                          string
	DurationValue                  uint32
	TargetValue                    uint32
	CustomTargetValueLow           uint32
	CustomTargetValueHigh          uint32
	SecondaryTargetValue           uint32
	SecondaryCustomTargetValueLow  uint32
	SecondaryCustomTargetValueHigh uint32
	MessageIndex                   typedef.MessageIndex
	ExerciseCategory               typedef.ExerciseCategory
	CategorySubtype                uint16
	LocalCategoryId                uint16
	ExerciseName                   uint16
	ExerciseWeight                 uint16 // Scale: 100; Units: kg
	WeightDisplayUnit              typedef.FitBaseUnit
	DurationType                   typedef.WktStepDuration
	TargetType                     typedef.WktStepTarget
	Intensity                      typedef.Intensity
	Equipment                      typedef.WorkoutEquipment
	SecondaryTargetType            typedef.WktStepTarget
	SortOrder                      int
	RoadBookId                     int64      // 路书id
	RoadBook                       *RouteBook `bun:"rel:belongs-to,join:road_book_id=id"` // 路书id

	UnknownFields   []proto.Field          `bun:",jsonb"` // UnknownFields are fields that are exist but they are not defined in Profile.xlsx
	DeveloperFields []proto.DeveloperField `bun:",jsonb"` // DeveloperFields are custom data fields [Added since protocol version 2.0]
}

/**
这是佳明(Garmin) FIT文件中定义的`ExerciseCategory`（运动类别）枚举类型，用Go语言实现。每个枚举值代表一种特定的运动或训练类别。下面是每个类型的解释：

1. `ExerciseCategoryBenchPress` (0) - 卧推
2. `ExerciseCategoryCalfRaise` (1) - 提踵（小腿训练）
3. `ExerciseCategoryCardio` (2) - 有氧运动
4. `ExerciseCategoryCarry` (3) - 负重行走
5. `ExerciseCategoryChop` (4) - 伐木式训练（旋转核心训练）
6. `ExerciseCategoryCore` (5) - 核心训练
7. `ExerciseCategoryCrunch` (6) - 卷腹
8. `ExerciseCategoryCurl` (7) - 弯举（通常是肱二头肌）
9. `ExerciseCategoryDeadlift` (8) - 硬拉
10. `ExerciseCategoryFlye` (9) - 飞鸟（胸肌训练）
11. `ExerciseCategoryHipRaise` (10) - 臀部提升
12. `ExerciseCategoryHipStability` (11) - 髋关节稳定性训练
13. `ExerciseCategoryHipSwing` (12) - 髋关节摆动（如壶铃摇摆）
14. `ExerciseCategoryHyperextension` (13) - 超伸展（背部训练）
15. `ExerciseCategoryLateralRaise` (14) - 侧平举（肩部训练）
16. `ExerciseCategoryLegCurl` (15) - 腿弯举（腘绳肌训练）
17. `ExerciseCategoryLegRaise` (16) - 抬腿（核心/髋部训练）
18. `ExerciseCategoryLunge` (17) - 弓步
19. `ExerciseCategoryOlympicLift` (18) - 奥林匹克举重（如抓举、挺举）
20. `ExerciseCategoryPlank` (19) - 平板支撑
21. `ExerciseCategoryPlyo` (20) - 增强式训练（爆发力训练）
22. `ExerciseCategoryPullUp` (21) - 引体向上
23. `ExerciseCategoryPushUp` (22) - 俯卧撑
24. `ExerciseCategoryRow` (23) - 划船动作
25. `ExerciseCategoryShoulderPress` (24) - 肩推
26. `ExerciseCategoryShoulderStability` (25) - 肩部稳定性训练
27. `ExerciseCategoryShrug` (26) - 耸肩（斜方肌训练）
28. `ExerciseCategorySitUp` (27) - 仰卧起坐
29. `ExerciseCategorySquat` (28) - 深蹲
30. `ExerciseCategoryTotalBody` (29) - 全身训练
31. `ExerciseCategoryTricepsExtension` (30) - 肱三头肌伸展
32. `ExerciseCategoryWarmUp` (31) - 热身
33. `ExerciseCategoryRun` (32) - 跑步
34. `ExerciseCategoryUnknown` (65534) - 未知类别
35. `ExerciseCategoryInvalid` (0xFFFF) - 无效值

这些类别用于在Garmin设备或相关应用中分类和记录不同类型的锻炼和训练。每个类别对应特定的运动类型或肌肉群训练。
*/

// ===user_workout_template ===

// PlanTemplate 计划模板  用于生成计划
// Deprecated
type PlanTemplate struct { // 一个计划 设置7天为一个周期
	bun.BaseModel      `bun:"table:user_plan_template"`
	Id                 int64 `bun:"id,pk,autoincrement"`
	UserId             int64
	Name               string
	startTime          int64
	endTime            int64
	IsActive           bool
	CycleLength        int                       //周期总天数
	CycleDay           int                       // 第几天
	PlanTemplateDetail []*UserPlanTemplateDetail `bun:"rel:has-many,join:id=plan_id"`
}

// PlanTemplate : UserPlanTemplateDetail = 1:n

// Deprecated
type UserPlanTemplateDetail struct { // 第几天
	bun.BaseModel                 `bun:"table:user_plan_template_detail"`
	Id                            int64 `bun:"id,pk,autoincrement"`
	PlanId                        int64
	CycleDay                      int                              // 第几天
	PlanTemplateDetailDietaryDate *PlanTemplateDetailDietaryDate   `bun:"rel:has-one,join:id=plan_template_detail_id"`
	PlanTemplateDetailDietaries   []*PlanTemplateDetailDietary     `bun:"rel:has-many,join:id=plan_template_detail_id"`
	PlanTemplateDetailWorkouts    []*UserPlanTemplateDetailWorkout `bun:"rel:has-many,join:id=plan_template_detail_id"`
}

// UserPlanTemplateDetail: PlanTemplateDetailDietaryDate  = 1:1

type PlanTemplateDetailDietaryDate struct { // 某天， 计划吃多少
	bun.BaseModel          `bun:"table:user_plan_template_detail_dietary"`
	Id                     int64   `bun:"id,pk,autoincrement"`
	PlanTemplateDetailId   int64   `bun:"plan_template_detail_id,unique"`
	CarbohydrateMultiplier float64 // 体重倍数
	ProteinMultiplier      float64 // 体重倍数
	FatMultiplier          float64 // 体重倍数
	Carbohydrate           float64 // g数
	Protein                float64 // g数
	Fat                    float64 // g数
	Kcal                   float64
	Kj                     float64
}

// UserPlanTemplateDetail: PlanTemplateDetailDietary  = 1:n（n可以为0）

// Deprecated
type PlanTemplateDetailDietary struct { // 某天，某次 计划吃多少
	bun.BaseModel          `bun:"table:user_plan_template_detail_dietary"`
	Id                     int64   `bun:"id,pk,autoincrement"`
	PlanTemplateDetailId   int64   `bun:"plan_template_detail_id"`
	CarbohydrateMultiplier float64 // 体重倍数
	ProteinMultiplier      float64 // 体重倍数
	FatMultiplier          float64 // 体重倍数
	Carbohydrate           float64 // g数
	Protein                float64 // g数
	Fat                    float64 // g数
	Kcal                   float64
	Kj                     float64
	// 第几餐
	SortOrder                       int                                // 排序
	PlanTemplateDetailFoodRelations []*PlanTemplateDetailFoodRelations `bun:"rel:has-many,join:id=plan_template_detail_dietary_id"`
}

// PlanTemplateDetailDietary : PlanTemplateDetailDietary = 1:n
// Deprecated
type PlanTemplateDetailFoodRelations struct { // 按菜谱吃，按计划吃，具体怎么吃
	bun.BaseModel               `bun:"table:user_plan_template_detail_food_relations"`
	Id                          int64 `bun:"id,pk,autoincrement"`
	PlanTemplateDetailDietaryId int64 `bun:"plan_template_detail_dietary_id"`
	FoodId                      int64
	MenuId                      int64
	Weight                      float64 // 克数
}

type UserPlanTemplateDetailWorkout struct {
	bun.BaseModel        `bun:"table:user_plan_template_detail_workout,alias:uptdw"`
	Id                   int64 `bun:"id,pk,autoincrement"`
	PlanTemplateDetailId int64 `bun:"plan_template_detail_id"`
	WktName              string
	WktDescription       string                      // Description of the workout
	Capabilities         typedef.WorkoutCapabilities `bun:"-"` // Base: uint32z //能力 需要展开成多个字段

	CapabilitiesInterval         bool
	CapabilitiesCustom           bool
	CapabilitiesFitnessEquipment bool
	CapabilitiesFirstbeat        bool
	CapabilitiesNewLeaf          bool
	CapabilitiesTcx              bool
	CapabilitiesSpeed            bool
	CapabilitiesHeartRate        bool
	CapabilitiesDistance         bool
	CapabilitiesCadence          bool
	CapabilitiesPower            bool
	CapabilitiesGrade            bool
	CapabilitiesResistance       bool
	CapabilitiesProtected        bool

	MessageIndex  typedef.MessageIndex //uint16
	NumValidSteps uint16               // number of valid steps
	PoolLength    uint16               // Scale: 100; Units: m
	//Sport typedef.Sport
	//SubSport typedef.SubSport
	SportId        int64
	Sport          *Sport `bun:"rel:belongs-to,join:sport_id=id"`
	PoolLengthUnit typedef.DisplayMeasure

	UnknownFields   []proto.Field          `bun:",jsonb"` // UnknownFields are fields that are exist but they are not defined in Profile.xlsx
	DeveloperFields []proto.DeveloperField `bun:",jsonb"` // DeveloperFields are custom data fields [Added since protocol version 2.0]

	SortOrder          int
	WorkoutSteps       []*PlanTemplateDetailWorkoutStep `bun:"rel:has-many,join:id=plan_template_detail_workout_id"`
	PlanTemplateDetail *UserPlanTemplateDetail          `bun:"rel:belongs-to,join:plan_template_detail_id=id"`
	// Steps []*UserPlanTemplateDetailWorkoutStep `bun:"rel:has-many,join:id=plan_template_detail_workout_id"` // 关联 Workout Steps
	// Sport *SysSport `bun:"rel:belongs-to,join:sport_id=id"` // 关联运动类型
	// 关系 (Relationships)
	ActivityDefinitions []*ActivityDefinition `bun:"rel:has-many,join:id=related_internal_template_workout_id"` // **新增**: 此模板被哪些 ActivityDefinition 引用
}

type PlanTemplateDetailWorkoutStep struct {
	bun.BaseModel                  `bun:"table:user_plan_template_detail_workout_step"`
	Id                             int64 `bun:"id,pk,autoincrement"`
	PlanTemplateDetailWorkoutId    int64 `bun:"plan_template_detail_workout_id"`
	WktStepName                    string
	Notes                          string
	DurationValue                  uint32
	TargetValue                    uint32
	CustomTargetValueLow           uint32
	CustomTargetValueHigh          uint32
	SecondaryTargetValue           uint32
	SecondaryCustomTargetValueLow  uint32
	SecondaryCustomTargetValueHigh uint32
	MessageIndex                   typedef.MessageIndex     //uint16
	ExerciseCategory               typedef.ExerciseCategory //大类
	CategorySubtype                uint16                   // 佳明细分
	LocalCategoryId                uint16                   // 本地数据库id
	ExerciseName                   uint16
	ExerciseWeight                 uint16 // Scale: 100; Units: kg
	WeightDisplayUnit              typedef.FitBaseUnit
	DurationType                   typedef.WktStepDuration
	TargetType                     typedef.WktStepTarget
	Intensity                      typedef.Intensity
	Equipment                      typedef.WorkoutEquipment
	SecondaryTargetType            typedef.WktStepTarget
	SortOrder                      int
	RoadBookId                     int64      // 路书id
	RoadBook                       *RouteBook `bun:"rel:belongs-to,join:road_book_id=id"` // 路书id

	UnknownFields   []proto.Field          `bun:",jsonb"` // UnknownFields are fields that are exist but they are not defined in Profile.xlsx
	DeveloperFields []proto.DeveloperField `bun:",jsonb"` // DeveloperFields are custom data fields [Added since protocol version 2.0]
}

// ActivitySummaryObservation 结构体代表 activity_summary_observations 表
type ActivitySummaryObservation struct {
	bun.BaseModel `bun:"table:activity_summary_observations,alias:aso"`

	SummaryObservationID     int64     `bun:"summary_observation_id,pk,autoincrement"`
	UserID                   int64     `bun:"user_id,notnull"`
	SourceUserActivityID     int64     `bun:"source_user_activity_id,notnull"`
	PartOfCarePlanActivityID *int64    `bun:"part_of_care_plan_activity_id,nullzero"`
	MeasurementTypeID        int32     `bun:"measurement_type_id,notnull"`
	ObservationTimestamp     time.Time `bun:"observation_timestamp,notnull"`
	ValueNumeric             *float64  `bun:"value_numeric,type:numeric(18,9),nullzero"`
	ValueString              *string   `bun:"value_string,nullzero"`
	UnitID                   *int32    `bun:"unit_id,nullzero"`
	FhirObservationID        *string   `bun:"fhir_observation_id,unique,nullzero"`
	Status                   string    `bun:"status,notnull,default:'final'"`
	Notes                    *string   `bun:"notes,nullzero"`
	CreatedAt                time.Time `bun:"created_at,notnull,default:current_timestamp"`
	UpdatedAt                time.Time `bun:"updated_at,notnull,default:current_timestamp"`

	// 关系 (Relationships)
	User                   *User             `bun:"rel:belongs-to,join:user_id=user_id"`
	SourceUserActivity     *UserActivity     `bun:"rel:belongs-to,join:source_user_activity_id=id"` // 假设 UserActivity struct 已定义
	PartOfCarePlanActivity *CarePlanActivity `bun:"rel:belongs-to,join:part_of_care_plan_activity_id=activity_id"`
	MeasurementType        *MeasurementType  `bun:"rel:belongs-to,join:measurement_type_id=measurement_type_id"`
	Unit                   *Unit             `bun:"rel:belongs-to,join:unit_id=unit_id"`
}
